python - 按键对 dict 列表进行排序。如果缺少键,则假定为连续编号

标签 python sorting

我想按“pos”键对字典列表进行排序。但是,如果字典中缺少“pos”,我想保持项目的顺序并假设“pos”是列表中项目的从 1 开始的索引。

这工作正常,只要所有列表项都不同:

L = [
    {   "id": "1" }, # assume pos: 1
    {   "id": "2" }, # assume pos: 2
    {   "id": "3" }, # assume pos: 3
    {   "id": "4" }, # assume pos: 4
    {   "id": "ZZZ" }, # assume pos: 5
    {   "id": "AAA" }, # assume pos: 6
    {   "id": "ABC", "pos": 3.2 },
    {   "id": "XYZ", "pos": 3.1 },
]

s = sorted(L,key=lambda i:i.get("pos",L.index(i)+1))
print(s)

输出:
[{'id': '1'}, {'id': '2'}, {'id': '3'}, {'id': 'XYZ', 'pos': 3.1}, {'id': 'ABC', 'pos': 3.2}, {'id': '4'}, {'id': 'ZZZ'}, {'id': 'AAA'}]

但是如果我有多个相同的项目,它就会失败,因为那时 list.index将返回第一次出现,而不是“假定位置”。
L = [
    {   "id": "1" }, # assume pos: 1
    {   "id": "1" }, # assume pos: 2
    {   "id": "1" }, # assume pos: 3
    {   "id": "1" }, # assume pos: 4
    {   "id": "1" }, # assume pos: 5
    {   "id": "AAA" }, # assume pos: 6
    {   "id": "ABC", "pos": 3.2 },
    {   "id": "XYZ", "pos": 3.1 },
]

s = sorted(L,key=lambda i:i.get("pos",L.index(i)+1))
print(s)

实际输出:
[{'id': '1'}, {'id': '1'}, {'id': '1'}, {'id': '1'}, {'id': '1'}, {'id': 'XYZ', 'pos': 3.1}, {'id': 'ABC', 'pos': 3.2}, {'id': 'AAA'}]

预期输出:
[{'id': '1'}, {'id': '1'}, {'id': '1'}, {'id': 'XYZ', 'pos': 3.1}, {'id': 'ABC', 'pos': 3.2}, {'id': '1'}, {'id': '1'}, {'id': 'AAA'}]

如何更改排序以返回预期的输出?

注意:项目 ID 不保证按任何顺序排列,即 1,2,3,4,AAA,ABC,XYZ是随意选择的。

最佳答案

使用 enumerate :

L = [
    {"id": "1"},  # assume pos: 1
    {"id": "2"},  # assume pos: 2
    {"id": "3"},  # assume pos: 3
    {"id": "4"},  # assume pos: 4
    {"id": "ZZZ"},  # assume pos: 5
    {"id": "AAA"},  # assume pos: 6
    {"id": "ABC", "pos": 3.2},
    {"id": "XYZ", "pos": 3.1},
]

result = [e for _, e in sorted(enumerate(L, 1), key=lambda x: x[1].get("pos", x[0]))]

print(result)

输出
[{'id': '1'}, {'id': '2'}, {'id': '3'}, {'id': 'XYZ', 'pos': 3.1}, {'id': 'ABC', 'pos': 3.2}, {'id': '4'}, {'id': 'ZZZ'}, {'id': 'AAA'}]

对于重复示例:
L = [
    {"id": "1"},  # assume pos: 1
    {"id": "1"},  # assume pos: 2
    {"id": "1"},  # assume pos: 3
    {"id": "1"},  # assume pos: 4
    {"id": "1"},  # assume pos: 5
    {"id": "AAA"},  # assume pos: 6
    {"id": "ABC", "pos": 3.2},
    {"id": "XYZ", "pos": 3.1},
]

result = [e for _, e in sorted(enumerate(L, 1), key=lambda x: x[1].get("pos", x[0]))]

print(result)

输出
[{'id': '1'}, {'id': '1'}, {'id': '1'}, {'id': 'XYZ', 'pos': 3.1}, {'id': 'ABC', 'pos': 3.2}, {'id': '1'}, {'id': '1'}, {'id': 'AAA'}]

一个可能更清洁的替代方法是使用 itertools.count :
from itertools import count

counter = count(1)

result = sorted(L, key=lambda x: x.get("pos", next(counter)))
print(result)

关于python - 按键对 dict 列表进行排序。如果缺少键,则假定为连续编号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58301650/

相关文章:

c++ - 使用标准 :sort to sort locally

python - 如何在python中为大数据创建哈希表?

python - 搜索没有 html 标签的漂亮的 soup 输出

python - 在 Ubuntu 14.04 上使用 Python 连接到 Microsoft Azure SQL 数据库

python - numpy.array 中的零条目是否占用内存?

Python 双重排序与分割字符串

php - 在具有多个条件的PHP中对多维数组进行排序

algorithm - Sphinx 怎么能这么快地进行排序?

python - 如何使用 requests.put() 通过 Python 上传文件?

python - 无法在 Django 上运行服务器(连接被拒绝)