Pythonic 以棘手的顺序对字典列表进行排序
Pythonic sort a list of dictionaries in a tricky order
我有一个按正确顺序排序的 ID 列表:
ids = [1, 2, 4, 6, 5, 0, 3]
我还有一个字典列表,以某种随机方式排序:
rez = [{'val': 7, 'id': 1}, {'val': 8, 'id': 2}, {'val': 2, 'id': 3}, {'val': 0, 'id': 4}, {'val': -1, 'id': 5}, {'val': -4, 'id': 6}, {'val': 9, 'id': 0}]
我的目的是按照 ids
:
对应的方式对 rez
列表进行排序
rez = [{'val': 7, 'id': 1}, {'val': 8, 'id': 2}, {'val': 0, 'id': 4}, {'val': -4, 'id': 6}, {'val': -1, 'id': 5}, {'val': 9, 'id': 0}, {'val': 2, 'id': 3}]
我试过了:
rez.sort(key = lambda x: ids.index(x['id']))
但是这种方式对我来说太慢了,因为 len(ids) > 150K,而且每个字典实际上有很多键(有些值是字符串)。任何建议如何以最 pythonic 但仍然最快的方式做到这一点?
我认为您的方向是正确的。如果你需要加快它的速度,因为你的列表太长而且你有二次复杂度,你可以先把列表变成字典,将id映射到它们各自的索引。
indices = {id_: pos for pos, id_ in enumerate(ids)}
rez.sort(key = lambda x: indices[x['id']])
这样,indices
就是{0: 5, 1: 0, 2: 1, 3: 6, 4: 2, 5: 4, 6: 3}
,rez
就是
[{'id': 1, 'val': 7},
{'id': 2, 'val': 8},
{'id': 4, 'val': 0},
{'id': 6, 'val': -4},
{'id': 5, 'val': -1},
{'id': 0, 'val': 9},
{'id': 3, 'val': 2}]
您不需要 sort
因为 ids
指定了结果的整个排序。您只需要通过它们的 id 选择正确的元素:
rez_dict = {d['id']:d for d in rez}
rez_ordered = [rez_dict[id] for id in ids]
给出:
>>> rez_ordered
[{'id': 1, 'val': 7}, {'id': 2, 'val': 8}, {'id': 4, 'val': 0}, {'id': 6, 'val': -4}, {'id': 5, 'val': -1}, {'id': 0, 'val': 9}, {'id': 3, 'val': 2}]
这应该比排序更快,因为它可以在平均线性时间内完成,而排序是 O(nlogn)。
请注意,这假设每个 ID 都有一个条目,如您的示例所示。
我有一个按正确顺序排序的 ID 列表:
ids = [1, 2, 4, 6, 5, 0, 3]
我还有一个字典列表,以某种随机方式排序:
rez = [{'val': 7, 'id': 1}, {'val': 8, 'id': 2}, {'val': 2, 'id': 3}, {'val': 0, 'id': 4}, {'val': -1, 'id': 5}, {'val': -4, 'id': 6}, {'val': 9, 'id': 0}]
我的目的是按照 ids
:
rez
列表进行排序
rez = [{'val': 7, 'id': 1}, {'val': 8, 'id': 2}, {'val': 0, 'id': 4}, {'val': -4, 'id': 6}, {'val': -1, 'id': 5}, {'val': 9, 'id': 0}, {'val': 2, 'id': 3}]
我试过了:
rez.sort(key = lambda x: ids.index(x['id']))
但是这种方式对我来说太慢了,因为 len(ids) > 150K,而且每个字典实际上有很多键(有些值是字符串)。任何建议如何以最 pythonic 但仍然最快的方式做到这一点?
我认为您的方向是正确的。如果你需要加快它的速度,因为你的列表太长而且你有二次复杂度,你可以先把列表变成字典,将id映射到它们各自的索引。
indices = {id_: pos for pos, id_ in enumerate(ids)}
rez.sort(key = lambda x: indices[x['id']])
这样,indices
就是{0: 5, 1: 0, 2: 1, 3: 6, 4: 2, 5: 4, 6: 3}
,rez
就是
[{'id': 1, 'val': 7},
{'id': 2, 'val': 8},
{'id': 4, 'val': 0},
{'id': 6, 'val': -4},
{'id': 5, 'val': -1},
{'id': 0, 'val': 9},
{'id': 3, 'val': 2}]
您不需要 sort
因为 ids
指定了结果的整个排序。您只需要通过它们的 id 选择正确的元素:
rez_dict = {d['id']:d for d in rez}
rez_ordered = [rez_dict[id] for id in ids]
给出:
>>> rez_ordered
[{'id': 1, 'val': 7}, {'id': 2, 'val': 8}, {'id': 4, 'val': 0}, {'id': 6, 'val': -4}, {'id': 5, 'val': -1}, {'id': 0, 'val': 9}, {'id': 3, 'val': 2}]
这应该比排序更快,因为它可以在平均线性时间内完成,而排序是 O(nlogn)。
请注意,这假设每个 ID 都有一个条目,如您的示例所示。