[英]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.