通过第二个有序列表中的键的出现对字典列表进行排序

时间:2014-09-30 16:56:48

标签: python list sorting python-3.x dictionary

我有两个清单。我的第一个列表first_list_ordered包含字符串。

first_list_ordered = ["id1", "id2", "id3", "id4", "id5", "id6", "id7"]

我的第二个列表second_list_unsorted包含至少包含一个名为id的密钥的字典,其值可能会显示在first_list_ordered中。

second_list_unordered = [{"id": "id6", "content": "sth"},
                         {"id": "id4", "content": "sth"},
                         {"id": "id1", "content": "sth"},
                         {"id": "id3", "content": "sth"}]

现在我想按照第一个列表中id的值的外观顺序对第二个列表进行排序。 结果应如下所示:

result = [{"id": "id1", "content": "sth"},
          {"id": "id3", "content": "sth"},
          {"id": "id4", "content": "sth"},
          {"id": "id6", "content": "sth"}]

因此,如果您在id中创建每个字典的所有值second_list_unordered的列表,则会得到first_list_ordered的无序子集。

我的方法如下:

>>> first_list_ordered = ["id1", "id2", "id3", "id4", "id5", "id6", "id7"]
>>> second_list_unordered = [{"id": "id6", "content": "sth"}, {"id": "id4", "content": "sth"}, {"id": "id1", "content": "sth"}, {"id": "id3", "content": "sth"}]
>>> indices = {c: i for i, c in enumerate(first_list_ordered)}
>>> result = sorted(second_list_unordered, key=indices.get)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'dict'

显然它并没有这样做......现在我被卡住了。

感谢任何提示!

2 个答案:

答案 0 :(得分:1)

您需要将id密钥传递给indices.get,而不是整个字典:

result = sorted(second_list_unordered, key=lambda d: indices.get(d['id']))

演示:

>>> from pprint import pprint
>>> first_list_ordered = ["id1", "id2", "id3", "id4", "id5", "id6", "id7"]
>>> second_list_unordered = [{"id": "id6", "content": "sth"},
...                          {"id": "id4", "content": "sth"},
...                          {"id": "id1", "content": "sth"},
...                          {"id": "id3", "content": "sth"}]
>>> indices = {c: i for i, c in enumerate(first_list_ordered)}
>>> sorted(second_list_unordered, key=lambda d: indices.get(d['id']))
[{'content': 'sth', 'id': 'id1'}, {'content': 'sth', 'id': 'id3'}, {'content': 'sth', 'id': 'id4'}, {'content': 'sth', 'id': 'id6'}]
>>> pprint(_)
[{'content': 'sth', 'id': 'id1'},
 {'content': 'sth', 'id': 'id3'},
 {'content': 'sth', 'id': 'id4'},
 {'content': 'sth', 'id': 'id6'}]

为了让它更有趣,改组first_list_ordered,因为id值的排序顺序在某种程度上模糊了目的:

>>> import random
>>> random.shuffle(first_list_ordered)
>>> first_list_ordered
['id2', 'id7', 'id1', 'id4', 'id6', 'id5', 'id3']
>>> indices = {c: i for i, c in enumerate(first_list_ordered)}
>>> sorted(second_list_unordered, key=lambda d: indices.get(d['id']))
[{'content': 'sth', 'id': 'id1'}, {'content': 'sth', 'id': 'id4'}, {'content': 'sth', 'id': 'id6'}, {'content': 'sth', 'id': 'id3'}]
>>> pprint(_)
[{'content': 'sth', 'id': 'id1'},
 {'content': 'sth', 'id': 'id4'},
 {'content': 'sth', 'id': 'id6'},
 {'content': 'sth', 'id': 'id3'}]

答案 1 :(得分:0)

如果速度不是问题,那么为什么不手动呢?

这里便宜又脏的oneliner。

In [55]: second_list_unordered = [{"id": "id6", "content": "sth"}, {"id": "id4", "content": "sth"}, {"id": "id1", "content": "sth"}, {"id": "id3", "content": "sth"}]

In [56]: first_list_ordered = ["id1", "id2", "id3", "id4", "id5", "id6", "id7"]
In [57]: f = first_list_ordered

In [58]: s = second_list_unordered

In [59]: [oval[0] for oval in [[val for val in s if (val["id"] == key)] for key in f] if oval]
Out[59]: 
[{'content': 'sth', 'id': 'id1'},
 {'content': 'sth', 'id': 'id3'},
 {'content': 'sth', 'id': 'id4'},
 {'content': 'sth', 'id': 'id6'}]

In [60]: fff = ["id3", "id4", "id5", "id2", "id1", "id6", "id7"]

In [61]: [oval[0] for oval in [[val for val in s if (val["id"] == key)] for key in fff] if oval]
Out[61]: 
[{'content': 'sth', 'id': 'id3'},
 {'content': 'sth', 'id': 'id4'},
 {'content': 'sth', 'id': 'id1'},
 {'content': 'sth', 'id': 'id6'}]

相同,但分为两个操作以便理解:

In [62]: temp = [[val for val in s if (val["id"] == key)] for key in f]

In [63]: [val[0] for val in temp if val]
Out[63]: 
[{'content': 'sth', 'id': 'id1'},
 {'content': 'sth', 'id': 'id3'},
 {'content': 'sth', 'id': 'id4'},
 {'content': 'sth', 'id': 'id6'}]