简体   繁体   English

按键排序字典列表。 如果 key 缺失,假设一个连续的编号

[英]Sort a list of dict by key. If key is missing, assume a consecutive numbering

I want so sort a list of dictionaries by the key "pos".我想按“pos”键对字典列表进行排序。 However, if "pos" is missing in the dict, I want to keep the order of the item(s) and assume that "pos" is the item's 1-based index in the list.但是,如果字典中缺少“pos”,我想保持项目的顺序并假设“pos”是项目在列表中基于 1 的索引。

This is working fine, as long as all list items are different:这工作正常,只要所有列表项不同:

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: Output:

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

But it fails if I have multiple of the same items, because then list.index will return the first occurence, rather than the "assumed position".但如果我有多个相同的项目,它会失败,因为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)

Actual output:实际 output:

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

Expected output:预期 output:

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

How can the sorting be changed to return the expected output?如何更改排序以返回预期的 output?

Note: the item IDs are not guaranteed to be in any order, that means 1,2,3,4,AAA,ABC,XYZ have been chosen arbitrarily.注意:项目 ID 不保证按任何顺序排列,即1,2,3,4,AAA,ABC,XYZ已被任意选择。

Use 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)

Output Output

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

For the duplicates example:对于重复示例:

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 Output

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

A perhaps cleaner alternative is to use itertools.count :一个可能更清洁的替代方法是使用itertools.count

from itertools import count

counter = count(1)

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

We can do something like this:我们可以这样做:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM