[英]Sort a list of dict by key. If key is missing, assume a consecutive numbering
我想按“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)
Output:
[{'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)
實際 output:
[{'id': '1'}, {'id': '1'}, {'id': '1'}, {'id': '1'}, {'id': '1'}, {'id': 'XYZ', 'pos': 3.1}, {'id': 'ABC', 'pos': 3.2}, {'id': 'AAA'}]
預期 output:
[{'id': '1'}, {'id': '1'}, {'id': '1'}, {'id': 'XYZ', 'pos': 3.1}, {'id': 'ABC', 'pos': 3.2}, {'id': '1'}, {'id': '1'}, {'id': 'AAA'}]
如何更改排序以返回預期的 output?
注意:項目 ID 不保證按任何順序排列,即1,2,3,4,AAA,ABC,XYZ
已被任意選擇。
使用枚舉:
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)
Output
[{'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)
Output
[{'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)
我們可以這樣做:
d = [
{"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},
]
def my_compare(x):
if 'pos' in x[1]:
return x[1]['pos']
return x[0] + 1
sorted_d = [x[1] for x in sorted(enumerate(d), key=my_compare)]
expected_output = [
{'id': '1'},
{'id': '1'},
{'id': '1'},
{'id': 'XYZ','pos': 3.1},
{'id': 'ABC','pos': 3.2},
{'id': '1'},
{'id': '1'},
{'id': 'AAA'},
]
assert sorted_d == expected_output
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.