简体   繁体   中英

Sort a list of dictionary with order of specific key

I have a list of dict like this:

data = [{"uid": "a1", "name": "b1"}, 
        {"uid": "a3", "name": "b3"}, 
        {"uid": "a4", "name": "b4"},
        {"uid": "a5", "name": "b5"}]

Now I want to sort that list with the order of the uid field like this:

uid_order = ['a1', 'a5', 'a3', 'a4']

Which means the output should be:

[{"uid": "a1", "name": "b1"}, 
 {"uid": "a5", "name": "b5"},
 {"uid": "a3", "name": "b3"},
 {"uid": "a4", "name": "b4"}]

Of course, I can create a new empty list then use 2 for loops to check and add every element, but is there any elegant way (or better complexity) to do this?

O(n) solution:

>>> [*map({d['uid']: d for d in data}.get, uid_order)]
[{'uid': 'a1', 'name': 'b1'},
 {'uid': 'a5', 'name': 'b5'},
 {'uid': 'a3', 'name': 'b3'},
 {'uid': 'a4', 'name': 'b4'}]

You can sort a list in place with it'ssort method if you want to avoid making a new list. This will use Timsort, which has O(n log n) complexity, much better than your suggested O(n^2) implementation:

uid_order = {k: i for i, k in enumerate(uid_order)}
data.sort(key=uid_order.get)

To speed up lookup into uid_order , I invert it into a dictionary (invert because a list maps index to item, while you want item to index). Instead of an O(n) lookup at each evaluation of the key, you have an O(1) lookup now.

An alternative way to make the dictionary using only function calls:

uid_order = dict(map(reversed, enumerate(uid_order)))

See also: Python Sorting HOW TO

With thesorted -function you can specify a key that the function should sort after. You want to access the value of the "uid" key for each dictionary and that value's index in uid_order determines that dictionary's index in the sorted list:

sorted(data, key = lambda x: uid_order.index(x["uid"]))

What this code means is, each element of the list gets passed to the lambda -function. The resulting value is used as key to sort after.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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