Sorting a dictionary by value then by key
In [62]: y={100:1, 90:4, 99:3, 92:1, 101:1}
In [63]: sorted(y.items(), key=lambda x: (x[1],x[0]), reverse=True)
Out[63]: [(90, 4), (99, 3), (101, 1), (100, 1), (92, 1)]
The key=lambda x: (x[1],x[0])
tells sorted
that for each item x
in y.items()
, use (x[1],x[0])
as the proxy value to be sorted. Since x
is of the form (key,value)
, (x[1],x[0])
yields (value,key)
. This causes sorted
to sort by value
first, then by key
for tie-breakers.
reverse=True
tells sorted
to present the result in descending, rather than ascending order.
See this wiki page for a great tutorial on sorting in Python.
PS. I tried using key=reversed
instead, but reversed(x)
returns an iterator, which does not compare as needed here.
How do I sort a dictionary by value?
Python 3.7+ or CPython 3.6
Dicts preserve insertion order in Python 3.7+. Same in CPython 3.6, but it's an implementation detail.
>>> x = {1: 2, 3: 4, 4: 3, 2: 1, 0: 0}
>>> {k: v for k, v in sorted(x.items(), key=lambda item: item[1])}
{0: 0, 2: 1, 1: 2, 4: 3, 3: 4}
or
>>> dict(sorted(x.items(), key=lambda item: item[1]))
{0: 0, 2: 1, 1: 2, 4: 3, 3: 4}
Older Python
It is not possible to sort a dictionary, only to get a representation of a dictionary that is sorted. Dictionaries are inherently orderless, but other types, such as lists and tuples, are not. So you need an ordered data type to represent sorted values, which will be a list—probably a list of tuples.
For instance,
import operator
x = {1: 2, 3: 4, 4: 3, 2: 1, 0: 0}
sorted_x = sorted(x.items(), key=operator.itemgetter(1))
sorted_x
will be a list of tuples sorted by the second element in each tuple. dict(sorted_x) == x
.
And for those wishing to sort on keys instead of values:
import operator
x = {1: 2, 3: 4, 4: 3, 2: 1, 0: 0}
sorted_x = sorted(x.items(), key=operator.itemgetter(0))
In Python3 since unpacking is not allowed we can use
x = {1: 2, 3: 4, 4: 3, 2: 1, 0: 0}
sorted_x = sorted(x.items(), key=lambda kv: kv[1])
If you want the output as a dict, you can use collections.OrderedDict
:
import collections
sorted_dict = collections.OrderedDict(sorted_x)
Sorting a dictionary by value then key
You need to take advantage of the fact that the values are numbers.
>>> [v[0] for v in sorted(d.iteritems(), key=lambda(k, v): (-v, k))]
['peach', 'banana', 'beetroot', 'almond', 'apple']
python sort dictionary items by value and then key
MyDict = {0: {'Score': 80.0, 'studentName': 'dan'},
1: {'Score': 92.0, 'studentName': 'rob'},
2: {'Score': 10.0, 'StudentName': 'xyz'}}
This returns the list of key-value pairs in the dictionary, sorted by value from highest to lowest:
sorted(MyDict.items(), key=lambda x: x[1], reverse=True)
For the dictionary sorted by key, use the following:
sorted(MyDict.items(), reverse=True)
The return is a list of tuples because dictionaries themselves can't be sorted.
This can be both printed or sent into further computation.
How to sort a dictionary by value (DESC) then by key (ASC)?
Something like
In [1]: d = {'banana': 3, 'orange': 5, 'apple': 5}
In [2]: sorted(d.items(), key=lambda x: (-x[1], x[0]))
Out[2]: [('apple', 5), ('orange', 5), ('banana', 3)]
Sort a dict according to both key and value at the same time
There's not an easy way to say "this value, ascending, then this one, descending". However, if you negate each of a list of integers, then sort it, then that's the same as sorting it in reverse.
This defines a sorting key which is a tuple:
- The first value is each dict item's value.
- The second value is each dict item's key, but negated.
d = {0: 2, 2: 2, 3: 2, 1: 4, 4: 5}
def sort_key(item):
key, value = item
return value, -key
print(sorted(d.items(), key=sort_key))
This outputs:
[(3, 2), (2, 2), (0, 2), (1, 4), (4, 5)]
See? The items are grouped by value, and in the event of a tie, by key in descending order.
How do I sort a list of dictionaries by a value of the dictionary?
The sorted()
function takes a key=
parameter
newlist = sorted(list_to_be_sorted, key=lambda d: d['name'])
Alternatively, you can use operator.itemgetter
instead of defining the function yourself
from operator import itemgetter
newlist = sorted(list_to_be_sorted, key=itemgetter('name'))
For completeness, add reverse=True
to sort in descending order
newlist = sorted(list_to_be_sorted, key=itemgetter('name'), reverse=True)
sort dict by value then if equal by keys
reverse=true
applies to both elements of the tuple. That why your alphanumeric output is backwards.
To reverse the order on the first element of the tuple but not on the other you could negate the numbers:
sorted(w.items(),key= lambda a: (-a[1],a[0]))
If you ever run into problem where you need to sort on multiple tuple elements with varying ASC/DESC order and elements that are not easy to negate like integers you could use the following technique.
Modified multisort
from https://docs.python.org/3/howto/sorting.html#sort-stability-and-complex-sorts
Since the sorting is stable the following will work:
def multisort(xs, specs):
for i, reverse in reversed(specs):
xs.sort(key=lambda x: x[i], reverse=reverse)
return xs
items = [('to', 2), ('be', 2), ('or', 1), ('not', 1), ('ae', 2)]
multisort(items, [(0, False), (1, True)])
Output:
[('ae', 2), ('be', 2), ('to', 2), ('not', 1), ('or', 1)]
Related Topics
Extract a Page from a PDF as a Jpeg
How to Pick "X" Number of Unique Numbers from a List in Python
How to Insert Newlines on Argparse Help Text
How to Give a Pandas/Matplotlib Bar Graph Custom Colors
Is It Feasible to Compile Python to MAChine Code
Running Interactive Commands in Paramiko
Why Do Some Built-In Python Functions Only Have Pass
Sorting by a Custom List in Pandas
Conditionally Fill Column Values Based on Another Columns Value in Pandas
List of Dicts To/From Dict of Lists
Python 3.5 - "Geckodriver Executable Needs to Be in Path"
Different Ways of Clearing Lists