Pythonic以棘手的顺序对字典列表进行排序

时间:2015-01-15 15:54:46

标签: python list sorting dictionary

我有一个id列表,在正确的oder中排序:

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}]

我的目的是以与rez对应的方式对ids列表进行排序:

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,每个dict实际上有很多键(有些值有字符串)。有任何建议如何以最pythonic,但仍然最快的方式做到这一点?

2 个答案:

答案 0 :(得分:9)

您不需要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都有一个条目,如您的示例所示。

答案 1 :(得分:1)

我认为你走在正确的轨道上。如果你需要加快速度,因为你的列表太长并且你有二次复杂性,你可以先将列表转换为字典,然后将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}]