[英]Sort list of dictionaries by appearance of key in a second ordered list
I have two lists. 我有两个清单。 My first list
first_list_ordered
contains strings. 我的第一个列表
first_list_ordered
包含字符串。
first_list_ordered = ["id1", "id2", "id3", "id4", "id5", "id6", "id7"]
My second list second_list_unsorted
contains dictionaries with at least one key called id
, where the value might appear in first_list_ordered
. 我的第二个列表
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"}]
Now I would like to sort the second list by the appearance order of id
's value in the first list. 现在,我想按第一张列表中
id
值的出现顺序对第二张列表进行排序。 The result should look like this: 结果应如下所示:
result = [{"id": "id1", "content": "sth"},
{"id": "id3", "content": "sth"},
{"id": "id4", "content": "sth"},
{"id": "id6", "content": "sth"}]
So if you create a list of all values id
of every dict in second_list_unordered
you get a unordered subset of first_list_ordered
. 所以,如果你创建的所有值的列表
id
在每一个字典的second_list_unordered
你得到的无序的子集中first_list_ordered
。
My approach would look like: 我的方法如下所示:
>>> 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'
Obviously it doesn't work that way... now I'm stuck. 显然,这种方式是行不通的...现在我被卡住了。
Thanks for any hints! 感谢您的提示!
You need to pass the id
key in to indices.get
, not the whole dictionary: 您需要将
id
键传递给indices.get
,而不是整个字典:
result = sorted(second_list_unordered, key=lambda d: indices.get(d['id']))
Demo: 演示:
>>> 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'}]
To make it a little more interesting, shuffling the first_list_ordered
, as the sorted order of the id
values obscures the purpose somewhat: 为了使它更加有趣,将
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'}]
If speed is not an issue, then why not do it manually? 如果速度不是问题,那么为什么不手动进行呢?
Here cheap and dirty oneliner. 这里便宜又脏的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'}]
Same, but splitted in two operations for understanding: 相同,但为了理解而分为两个操作:
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'}]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.