Reputation: 1445
I am trying to sort a list of dictionaries. My goal is to sort dictionaries with multiple (possibly the same) keys in the same way, even if the dictionaries are in a different order or if the keys are in the dictionary in a different order.
In Python 2, I have used the following:
a = [{1: 2, 7: 8}, {7: 8, 3: 4}, {5: 6}]
b = [{3: 4, 7: 8}, {7: 8, 1: 2}, {5: 6}]
a.sort()
b.sort()
a
Out[20]: [{5: 6}, {1: 2, 7: 8}, {3: 4, 7: 8}]
b
Out[21]: [{5: 6}, {1: 2, 7: 8}, {3: 4, 7: 8}]
This succeeds in my goal of creating two sorted dictionaries that look exactly the same.
I am trying to do the same thing in Python 3, where .sort() does not work for a list of dictionaries.
I have tried different ways.
1.
sorted(a, key=lambda d: max(d.keys()))
This does not work:
a = [{1: 2, 7: 8}, {3: 4, 7: 8}, {5: 6}]
b = [{3: 4, 7: 8}, {1: 2, 7: 8}, {5: 6}]
a2 = sorted(a, key=lambda d: max(d.keys()))
b2 = sorted(b, key=lambda d: max(d.keys()))
a2
Out[1]: [{5: 6}, {1: 2, 7: 8}, {7: 8, 3: 4}]
b2
Out[2]: [{5: 6}, {3: 4, 7: 8}, {7: 8, 1: 2}]
2.
a2 = sorted([list(zip(x.keys(),x.values())) for x in a])
a3 = [{k: v for (k,v) in x} for x in a2]
This does not work:
a = [{1: 2, 7: 8}, {7: 8, 3: 4}, {5: 6}]
b = [{3: 4, 7: 8}, {7: 8, 1: 2}, {5: 6}]
a2 = sorted([list(zip(x.keys(),x.values())) for x in a])
a3 = [{k: v for (k,v) in x} for x in a2]
b2 = sorted([list(zip(x.keys(),x.values())) for x in b])
b3 = [{k: v for (k,v) in x} for x in b2]
a3
Out[1]: [{1: 2, 7: 8}, {5: 6}, {7: 8, 3: 4}]
b3
Out[2]: [{3: 4, 7: 8}, {5: 6}, {7: 8, 1: 2}]
Does anyone have an idea how I can get the Python 2 result in Python 3??
Upvotes: 4
Views: 10730
Reputation: 375
You need to use all items of each dict while sorting, and d.items()
iterates items in arbitrary order, so they need to be sorted. And this is your sorting key:
a = [{1: 2, 7: 8}, {7: 8, 3: 4}, {5: 6}]
b = [{3: 4, 7: 8}, {7: 8, 1: 2}, {5: 6}]
sorted(a, key=lambda d: sorted(d.items()))
Out: [{1: 2, 7: 8}, {3: 4, 7: 8}, {5: 6}]
sorted(b, key=lambda d: sorted(d.items()))
Out: [{1: 2, 7: 8}, {3: 4, 7: 8}, {5: 6}]
x = [{1: 2},{1: 3}]
y = [{1: 3},{1: 2}]
sorted(x, key=lambda d: sorted(d.items()))
Out: [{1: 2}, {1: 3}]
sorted(y, key=lambda d: sorted(d.items()))
Out: [{1: 2}, {1: 3}]
Note that sorted(a, key=...)
creates a new list, while a.sort(key=...)
makes sorting in place.
Upvotes: 3
Reputation: 4603
Sorting on all keys
in the dictionaries can be done with:
a.sort(key=lambda d: d.keys())
b.sort(key=lambda d: d.keys())
To get the result you want we need to sort the keys on ascending order as follows:
a.sort(key=lambda d: sorted(list(d.keys()), reverse=True))
b.sort(key=lambda d: sorted(list(d.keys()), reverse=True))
This gives the following result:
>>> a
[{5: 6}, {1: 2, 7: 8}, {3: 4, 7: 8}]
>>> b
[{5: 6}, {1: 2, 7: 8}, {3: 4, 7: 8}]
Edit: In order to sort based on the values as well (asked in the comments) the following might work:
a.sort(key=lambda d: sorted(list(d.keys()) + sorted(list(d.values())), reverse=True))
b.sort(key=lambda d: sorted(list(d.keys()) + sorted(list(d.values())), reverse=True))
Upvotes: 4