@steve‘s is actually the most elegant way of doing it.
For the “correct” way see the order keyword argument of numpy.ndarray.sort
However, you’ll need to view your array as an array with fields (a structured array).
The “correct” way is quite ugly if you didn’t initially define your array with fields…
As a quick example, to sort it and return a copy:
In [1]: import numpy as np
In [2]: a = np.array([[1,2,3],[4,5,6],[0,0,1]])
In [3]: np.sort(a.view('i8,i8,i8'), order=['f1'], axis=0).view(np.int)
Out[3]:
array([[0, 0, 1],
[1, 2, 3],
[4, 5, 6]])
To sort it in-place:
In [6]: a.view('i8,i8,i8').sort(order=['f1'], axis=0) #<-- returns None
In [7]: a
Out[7]:
array([[0, 0, 1],
[1, 2, 3],
[4, 5, 6]])
@Steve’s really is the most elegant way to do it, as far as I know…
The only advantage to this method is that the “order” argument is a list of the fields to order the search by. For example, you can sort by the second column, then the third column, then the first column by supplying order=[‘f1′,’f2′,’f0’].
You can sort on multiple columns as per Steve Tjoa’s method by using a stable sort like mergesort and sorting the indices from the least significant to the most significant columns:
a = a[a[:,2].argsort()] # First sort doesn't need to be stable.
a = a[a[:,1].argsort(kind='mergesort')]
a = a[a[:,0].argsort(kind='mergesort')]
a = ([[1, 2, 3], [4, 5, 6], [0, 0, 1]]);
a = sorted(a, key=lambda a_entry: a_entry[1])
print a
The output is:
[[[0, 0, 1], [1, 2, 3], [4, 5, 6]]]
回答 4
如果有人想在他们程序的关键部分使用排序,下面是对不同提案的性能比较:
import numpy as np
table = np.random.rand(5000,10)%timeit table.view('f8,f8,f8,f8,f8,f8,f8,f8,f8,f8').sort(order=['f9'], axis=0)1000 loops, best of 3:1.88 ms per loop
%timeit table[table[:,9].argsort()]10000 loops, best of 3:180µs per loop
import pandas as pd
df = pd.DataFrame(table)%timeit df.sort_values(9, ascending=True)1000 loops, best of 3:400µs per loop
In case someone wants to make use of sorting at a critical part of their programs here’s a performance comparison for the different proposals:
import numpy as np
table = np.random.rand(5000, 10)
%timeit table.view('f8,f8,f8,f8,f8,f8,f8,f8,f8,f8').sort(order=['f9'], axis=0)
1000 loops, best of 3: 1.88 ms per loop
%timeit table[table[:,9].argsort()]
10000 loops, best of 3: 180 µs per loop
import pandas as pd
df = pd.DataFrame(table)
%timeit df.sort_values(9, ascending=True)
1000 loops, best of 3: 400 µs per loop
So, it looks like indexing with argsort is the quickest method so far…
>>> a
array([[1,2],[0,0],[1,0],[0,2],[2,1],[1,0],[1,0],[0,0],[1,0],[2,2]])>>> a[np.lexsort(np.fliplr(a).T)]
array([[0,0],[0,0],[0,2],[1,0],[1,0],[1,0],[1,0],[1,2],[2,1],[2,2]])
I want to calculate an SVD and need to sort my eigenvalues in descending order. But I want to keep the mapping between eigenvalues and eigenvectors.
My eigenvalues were in the first row and the corresponding eigenvector below it in the same column.
So I want to sort a two-dimensional array column-wise by the first row in descending order.
My Solution
a = a[::, a[0,].argsort()[::-1]]
So how does this work?
a[0,] is just the first row I want to sort by.
Now I use argsort to get the order of indices.
I use [::-1] because I need descending order.
Lastly I use a[::, ...] to get a view with the columns in the right order.
A little more complicated lexsort example – descending on the 1st column, secondarily ascending on the 2nd. The tricks with lexsort are that it sorts on rows (hence the .T), and gives priority to the last.
It is an old question but if you need to generalize this to a higher than 2 dimension arrays, here is the solution than can be easily generalized:
np.einsum('ij->ij', a[a[:,1].argsort(),:])
This is an overkill for two dimensions and a[a[:,1].argsort()] would be enough per @steve’s answer, however that answer cannot be generalized to higher dimensions. You can find an example of 3D array in this question.
a =[('Al',2),('Bill',1),('Carol',2),('Abel',3),('Zeke',2),('Chris',1)]
b = sorted(sorted(a, key =lambda x : x[0]), key =lambda x : x[1], reverse =True)print(b)[('Abel',3),('Al',2),('Carol',2),('Zeke',2),('Bill',1),('Chris',1)]
I’m not sure if this is the most pythonic method …
I had a list of tuples that needed sorting 1st by descending integer values and 2nd alphabetically. This required reversing the integer sort but not the alphabetical sort. Here was my solution: (on the fly in an exam btw, I was not even aware you could ‘nest’ sorted functions)
def attr_sort(self, attrs=['someAttributeString']:'''helper to sort by the attributes named by strings of attrs in order'''returnlambda k:[ getattr(k, attr)for attr in attrs ]
然后使用它
# would defined elsewhere but showing here for consiseness
self.SortListA=['attrA','attrB']
self.SortListB=['attrC','attrA']
records =....#list of my objects to sort
records.sort(key=self.attr_sort(attrs=self.SortListA))# perhaps later nearby or in another function
more_records =....#another list
more_records.sort(key=self.attr_sort(attrs=self.SortListB))
It appears you could use a list instead of a tuple.
This becomes more important I think when you are grabbing attributes instead of ‘magic indexes’ of a list/tuple.
In my case I wanted to sort by multiple attributes of a class, where the incoming keys were strings. I needed different sorting in different places, and I wanted a common default sort for the parent class that clients were interacting with; only having to override the ‘sorting keys’ when I really ‘needed to’, but also in a way that I could store them as lists that the class could share
So first I defined a helper method
def attr_sort(self, attrs=['someAttributeString']:
'''helper to sort by the attributes named by strings of attrs in order'''
return lambda k: [ getattr(k, attr) for attr in attrs ]
then to use it
# would defined elsewhere but showing here for consiseness
self.SortListA = ['attrA', 'attrB']
self.SortListB = ['attrC', 'attrA']
records = .... #list of my objects to sort
records.sort(key=self.attr_sort(attrs=self.SortListA))
# perhaps later nearby or in another function
more_records = .... #another list
more_records.sort(key=self.attr_sort(attrs=self.SortListB))
This will use the generated lambda function sort the list by object.attrA and then object.attrB assuming object has a getter corresponding to the string names provided. And the second case would sort by object.attrC then object.attrA.
This also allows you to potentially expose outward sorting choices to be shared alike by a consumer, a unit test, or for them to perhaps tell you how they want sorting done for some operation in your api by only have to give you a list and not coupling them to your back end implementation.
Several years late to the party but I want to both sort on 2 criteria and use reverse=True. In case someone else wants to know how, you can wrap your criteria (functions) in parenthesis:
s = sorted(my_list, key=lambda i: ( criteria_1(i), criteria_2(i) ), reverse=True)
#First, here's a pure list version
my_sortLambdaLst =[lambda x,y:cmp(x[0], y[0]),lambda x,y:cmp(x[1], y[1])]def multi_attribute_sort(x,y):
r =0for l in my_sortLambdaLst:
r = l(x,y)if r!=0:return r #keep looping till you see a differencereturn r
Lst=[(4,2.0),(4,0.01),(4,0.9),(4,0.999),(4,0.2),(1,2.0),(1,0.01),(1,0.9),(1,0.999),(1,0.2)]Lst.sort(lambda x,y:multi_attribute_sort(x,y))#The Lambda of the Lambdafor rec inLst:print str(rec)
这是一种对对象列表进行排名的方法
class probe:def __init__(self, group, score):
self.group = group
self.score = score
self.rank =-1def set_rank(self, r):
self.rank = r
def __str__(self):return'\t'.join([str(self.group), str(self.score), str(self.rank)])defRankLst(inLst, group_lambda=lambda x:x.group, sortLambdaLst =[lambda x,y:cmp(x.group, y.group),lambda x,y:cmp(x.score, y.score)],SetRank_Lambda=lambda x, rank:x.set_rank(rank)):#Inner function is the only way (I could think of) to pass the sortLambdaLst into a sort functiondef multi_attribute_sort(x,y):
r =0for l in sortLambdaLst:
r = l(x,y)if r!=0:return r #keep looping till you see a differencereturn r
inLst.sort(lambda x,y:multi_attribute_sort(x,y))#Now Rank your probes
rank =0
last_group = group_lambda(inLst[0])for i in range(len(inLst)):
rec = inLst[i]
group = group_lambda(rec)if last_group == group:
rank+=1else:
rank=1
last_group = group
SetRank_Lambda(inLst[i], rank)#This is pure evil!! The lambda purists are gnashing their teethLst=[probe(4,2.0), probe(4,0.01), probe(4,0.9), probe(4,0.999), probe(4,0.2), probe(1,2.0), probe(1,0.01), probe(1,0.9), probe(1,0.999), probe(1,0.2)]RankLst(Lst, group_lambda=lambda x:x.group, sortLambdaLst =[lambda x,y:cmp(x.group, y.group),lambda x,y:cmp(x.score, y.score)],SetRank_Lambda=lambda x, rank:x.set_rank(rank))print'\t'.join(['group','score','rank'])for r inLst:print r
Here’s one way: You basically re-write your sort function to take a list of sort functions, each sort function compares the attributes you want to test, on each sort test, you look and see if the cmp function returns a non-zero return if so break and send the return value.
You call it by calling a Lambda of a function of a list of Lambdas.
Its advantage is that it does single pass through the data not a sort of a previous sort as other methods do. Another thing is that it sorts in place, whereas sorted seems to make a copy.
I used it to write a rank function, that ranks a list of classes where each object is in a group and has a score function, but you can add any list of attributes.
Note the un-lambda-like, though hackish use of a lambda to call a setter.
The rank part won’t work for an array of lists, but the sort will.
#First, here's a pure list version
my_sortLambdaLst = [lambda x,y:cmp(x[0], y[0]), lambda x,y:cmp(x[1], y[1])]
def multi_attribute_sort(x,y):
r = 0
for l in my_sortLambdaLst:
r = l(x,y)
if r!=0: return r #keep looping till you see a difference
return r
Lst = [(4, 2.0), (4, 0.01), (4, 0.9), (4, 0.999),(4, 0.2), (1, 2.0), (1, 0.01), (1, 0.9), (1, 0.999), (1, 0.2) ]
Lst.sort(lambda x,y:multi_attribute_sort(x,y)) #The Lambda of the Lambda
for rec in Lst: print str(rec)
Here’s a way to rank a list of objects
class probe:
def __init__(self, group, score):
self.group = group
self.score = score
self.rank =-1
def set_rank(self, r):
self.rank = r
def __str__(self):
return '\t'.join([str(self.group), str(self.score), str(self.rank)])
def RankLst(inLst, group_lambda= lambda x:x.group, sortLambdaLst = [lambda x,y:cmp(x.group, y.group), lambda x,y:cmp(x.score, y.score)], SetRank_Lambda = lambda x, rank:x.set_rank(rank)):
#Inner function is the only way (I could think of) to pass the sortLambdaLst into a sort function
def multi_attribute_sort(x,y):
r = 0
for l in sortLambdaLst:
r = l(x,y)
if r!=0: return r #keep looping till you see a difference
return r
inLst.sort(lambda x,y:multi_attribute_sort(x,y))
#Now Rank your probes
rank = 0
last_group = group_lambda(inLst[0])
for i in range(len(inLst)):
rec = inLst[i]
group = group_lambda(rec)
if last_group == group:
rank+=1
else:
rank=1
last_group = group
SetRank_Lambda(inLst[i], rank) #This is pure evil!! The lambda purists are gnashing their teeth
Lst = [probe(4, 2.0), probe(4, 0.01), probe(4, 0.9), probe(4, 0.999), probe(4, 0.2), probe(1, 2.0), probe(1, 0.01), probe(1, 0.9), probe(1, 0.999), probe(1, 0.2) ]
RankLst(Lst, group_lambda= lambda x:x.group, sortLambdaLst = [lambda x,y:cmp(x.group, y.group), lambda x,y:cmp(x.score, y.score)], SetRank_Lambda = lambda x, rank:x.set_rank(rank))
print '\t'.join(['group', 'score', 'rank'])
for r in Lst: print r
This modifies your original list (i.e. sorts in-place). To get a sorted copy of the list, without changing the original, use the sorted() function:
for x in sorted(mylist):
print x
However, the examples above are a bit naive, because they don’t take locale into account, and perform a case-sensitive sorting. You can take advantage of the optional parameter key to specify custom sorting order (the alternative, using cmp, is a deprecated solution, as it has to be evaluated multiple times – key is only computed once per element).
So, to sort according to the current locale, taking language-specific rules into account (cmp_to_key is a helper function from functools):
sorted(mylist, key=cmp_to_key(locale.strcoll))
And finally, if you need, you can specify a custom locale for sorting:
import locale
locale.setlocale(locale.LC_ALL, 'en_US.UTF-8') # vary depending on your lang/locale
assert sorted((u'Ab', u'ad', u'aa'),
key=cmp_to_key(locale.strcoll)) == [u'aa', u'Ab', u'ad']
Last note: you will see examples of case-insensitive sorting which use the lower() method – those are incorrect, because they work only for the ASCII subset of characters. Those two are wrong for any non-English data:
# this is incorrect!
mylist.sort(key=lambda x: x.lower())
# alternative notation, a bit faster, but still wrong
mylist.sort(key=str.lower)
import locale
locale.setlocale(locale.LC_ALL,'en_US.UTF-8')# vary depending on your lang/localeassert sorted((u'Ab', u'ad', u'aa'), cmp=locale.strcoll)==[u'aa', u'Ab', u'ad']# Without using locale.strcoll you get:assert sorted((u'Ab', u'ad', u'aa'))==[u'Ab', u'aa', u'ad']
But how does this handle language specific sorting rules? Does it take locale into account?
No, list.sort() is a generic sorting function. If you want to sort according to the Unicode rules, you’ll have to define a custom sort key function. You can try using the pyuca module, but I don’t know how complete it is.
Old question, but if you want to do locale-aware sorting without settinglocale.LC_ALL you can do so by using the PyICU library as suggested by this answer:
import icu # PyICU
def sorted_strings(strings, locale=None):
if locale is None:
return sorted(strings)
collator = icu.Collator.createInstance(icu.Locale(locale))
return sorted(strings, key=collator.getSortKey)
To sort above string the simple solution will be below one.
print ''.join(sorted(s))
回答 8
或许:
names =['Jasmine','Alberto','Ross','dig-dog']print("The solution for this is about this names being sorted:",sorted(names, key=lambda name:name.lower()))
names = ['Jasmine', 'Alberto', 'Ross', 'dig-dog']
print ("The solution for this is about this names being sorted:",sorted(names, key=lambda name:name.lower()))
What would be a nice way to go from {2:3, 1:89, 4:5, 3:0} to {1:89, 2:3, 3:0, 4:5}?
I checked some posts but they all use the “sorted” operator that returns tuples.
In[1]:import collections
In[2]: d ={2:3,1:89,4:5,3:0}In[3]: od = collections.OrderedDict(sorted(d.items()))In[4]: od
Out[4]:OrderedDict([(1,89),(2,3),(3,0),(4,5)])
没关系od打印出来的方式; 它会按预期工作:
In[11]: od[1]Out[11]:89In[12]: od[3]Out[12]:0In[13]:for k, v in od.iteritems():print k, v
....:189233045
Python 3
对于Python 3用户,需要使用.items()而不是.iteritems():
In[13]:for k, v in od.items():print(k, v)....:189233045
Standard Python dictionaries are unordered. Even if you sorted the (key,value) pairs, you wouldn’t be able to store them in a dict in a way that would preserve the ordering.
The easiest way is to use OrderedDict, which remembers the order in which the elements have been inserted:
In [1]: import collections
In [2]: d = {2:3, 1:89, 4:5, 3:0}
In [3]: od = collections.OrderedDict(sorted(d.items()))
In [4]: od
Out[4]: OrderedDict([(1, 89), (2, 3), (3, 0), (4, 5)])
Never mind the way od is printed out; it’ll work as expected:
In [11]: od[1]
Out[11]: 89
In [12]: od[3]
Out[12]: 0
In [13]: for k, v in od.iteritems(): print k, v
....:
1 89
2 3
3 0
4 5
Python 3
For Python 3 users, one needs to use the .items() instead of .iteritems():
In [13]: for k, v in od.items(): print(k, v)
....:
1 89
2 3
3 0
4 5
回答 1
字典本身没有这样的有序项目,如果您想按某种顺序将它们打印等,下面是一些示例:
在Python 2.4及更高版本中:
mydict ={'carl':40,'alan':2,'bob':1,'danny':3}for key in sorted(mydict):print"%s: %s"%(key, mydict[key])
给出:
alan:2
bob:1
carl:40
danny:3
(低于2.4的Python :)
keylist = mydict.keys()
keylist.sort()for key in keylist:print"%s: %s"%(key, mydict[key])
There are a number of Python modules that provide dictionary implementations which automatically maintain the keys in sorted order. Consider the sortedcontainers module which is pure-Python and fast-as-C implementations. There is also a performance comparison with other popular options benchmarked against one another.
Using an ordered dict is an inadequate solution if you need to constantly add and remove key/value pairs while also iterating.
>>> from sortedcontainers import SortedDict
>>> d = {2:3, 1:89, 4:5, 3:0}
>>> s = SortedDict(d)
>>> s.items()
[(1, 89), (2, 3), (3, 0), (4, 5)]
The SortedDict type also supports indexed location lookups and deletion which isn’t possible with the built-in dict type.
classSortedDisplayDict(dict):def __str__(self):return"{"+", ".join("%r: %r"%(key, self[key])for key in sorted(self))+"}">>> d =SortedDisplayDict({2:3,1:89,4:5,3:0})>>> d
{1:89,2:3,3:0,4:5}
As others have mentioned, dictionaries are inherently unordered. However, if the issue is merely displaying dictionaries in an ordered fashion, you can override the __str__ method in a dictionary subclass, and use this dictionary class rather than the builtin dict. Eg.
class SortedDisplayDict(dict):
def __str__(self):
return "{" + ", ".join("%r: %r" % (key, self[key]) for key in sorted(self)) + "}"
>>> d = SortedDisplayDict({2:3, 1:89, 4:5, 3:0})
>>> d
{1: 89, 2: 3, 3: 0, 4: 5}
Note, this changes nothing about how the keys are stored, the order they will come back when you iterate over them etc, just how they’re displayed with print or at the python console.
upd:
1. this also sorts nested objects (thanks @DanielF).
2. python dictionaries are unordered therefore this is sutable for print or assign to str only.
回答 8
在Python 3中。
>>> D1 ={2:3,1:89,4:5,3:0}>>>for key in sorted(D1):print(key, D1[key])
test_dict ={'a':1,'c':3,'b':{'b2':2,'b1':1}}def dict_reorder(item):return{k: sort_dict(v)if isinstance(v, dict)else v for k, v in sorted(item.items())}
reordered_dict = dict_reorder(test_dict)
Python dictionary was unordered before Python 3.6. In CPython implementation of Python 3.6, dictionary keeps the insertion order.
From Python 3.7, this will become a language feature.
The order-preserving aspect of this new implementation is considered
an implementation detail and should not be relied upon (this may
change in the future, but it is desired to have this new dict
implementation in the language for a few releases before changing the
language spec to mandate order-preserving semantics for all current
and future Python implementations; this also helps preserve
backwards-compatibility with older versions of the language where
random iteration order is still in effect, e.g. Python 3.5).
Performing list(d) on a dictionary returns a list of all the keys used
in the dictionary, in insertion order (if you want it sorted, just use
sorted(d) instead).
So unlike previous versions, you can sort a dict after Python 3.6/3.7. If you want to sort a nested dict including the sub-dict inside, you can do:
test_dict = {'a': 1, 'c': 3, 'b': {'b2': 2, 'b1': 1}}
def dict_reorder(item):
return {k: sort_dict(v) if isinstance(v, dict) else v for k, v in sorted(item.items())}
reordered_dict = dict_reorder(test_dict)
D1 = {2:3, 1:89, 4:5, 3:0}
sort_dic = {}
for i in sorted(D1):
sort_dic.update({i:D1[i]})
print sort_dic
{1: 89, 2: 3, 3: 0, 4: 5}
But this is not the correct way to do this, because, It could show a distinct behavior with different dictionaries, which I have learned recently. Hence perfect way has been suggested by Tim In the response of my Query which I am sharing here.
from collections import OrderedDict
sorted_dict = OrderedDict(sorted(D1.items(), key=lambda t: t[0]))
回答 13
我认为最简单的方法是按键对字典进行排序,然后将排序后的键:值对保存在新字典中。
dict1 ={'renault':3,'ford':4,'volvo':1,'toyota':2}
dict2 ={}# create an empty dict to store the sorted valuesfor key in sorted(dict1.keys()):ifnot key in dict2:# Depending on the goal, this line may not be neccessary
dict2[key]= dict1[key]
为了更清楚一点:
dict1 ={'renault':3,'ford':4,'volvo':1,'toyota':2}
dict2 ={}# create an empty dict to store the sorted valuesfor key in sorted(dict1.keys()):ifnot key in dict2:# Depending on the goal, this line may not be neccessary
value = dict1[key]
dict2[key]= value
I think the easiest thing is to sort the dict by key and save the sorted key:value pair in a new dict.
dict1 = {'renault': 3, 'ford':4, 'volvo': 1, 'toyota': 2}
dict2 = {} # create an empty dict to store the sorted values
for key in sorted(dict1.keys()):
if not key in dict2: # Depending on the goal, this line may not be neccessary
dict2[key] = dict1[key]
To make it clearer:
dict1 = {'renault': 3, 'ford':4, 'volvo': 1, 'toyota': 2}
dict2 = {} # create an empty dict to store the sorted values
for key in sorted(dict1.keys()):
if not key in dict2: # Depending on the goal, this line may not be neccessary
value = dict1[key]
dict2[key] = value
You can create a new dictionary by sorting the current dictionary by key as per your question.
This is your dictionary
d = {2:3, 1:89, 4:5, 3:0}
Create a new dictionary d1 by sorting this d using lambda function
d1 = dict(sorted(d.items(), key = lambda x:x[0]))
d1 should be {1: 89, 2: 3, 3: 0, 4: 5}, sorted based on keys in d.
回答 15
Python字典是无序的。通常,这不是问题,因为最常见的用例是进行查找。
执行所需操作的最简单方法是创建collections.OrderedDict按排序顺序插入元素。
ordered_dict = collections.OrderedDict([(k, d[k])for k in sorted(d.keys())])
如上面其他建议那样,如果需要迭代,则最简单的方法是迭代已排序的键。例子-
打印按键排序的值:
# create the dict
d ={k1:v1, k2:v2,...}# iterate by keys in sorted orderfor k in sorted(d.keys()):
value = d[k]# do something with k, value like printprint k, value
Python dicts are un-ordered. Usually, this is not a problem since the most common use case is to do a lookup.
The simplest way to do what you want would be to create a collections.OrderedDict inserting the elements in sorted order.
ordered_dict = collections.OrderedDict([(k, d[k]) for k in sorted(d.keys())])
If you need to iterated, as others above have suggested, the simplest way would be to iterate over sorted keys. Examples-
Print values sorted by keys:
# create the dict
d = {k1:v1, k2:v2,...}
# iterate by keys in sorted order
for k in sorted(d.keys()):
value = d[k]
# do something with k, value like print
print k, value
Get list of values sorted by keys:
values = [d[k] for k in sorted(d.keys())]
回答 16
我提出单行字典排序。
>> a ={2:3,1:89,4:5,3:0}>> c ={i:a[i]for i in sorted(a.keys())}>>print(c){1:89,2:3,3:0,4:5}[Finishedin0.4s]
This function will sort any dictionary recursively by its key. That is, if any value in the dictionary is also a dictionary, it too will be sorted by its key. If you are running on CPython 3.6 or greater, than a simple change to use a dict rather than an OrderedDict can be made.
from collections import OrderedDict
def sort_dict(d):
items = [[k, v] for k, v in sorted(d.items(), key=lambda x: x[0])]
for item in items:
if isinstance(item[1], dict):
item[1] = sort_dict(item[1])
return OrderedDict(items)
#return dict(items)
回答 18
伙计们,你让事情变得复杂了……这很简单
from pprint import pprint
Dict={'B':1,'A':2,'C':3}
pprint(Dict)
A timing comparison of the two methods in 2.7 shows them to be virtually identical:
>>> setup_string = "a = sorted(dict({2:3, 1:89, 4:5, 3:0}).items())"
>>> timeit.timeit(stmt="[(k, val) for k, val in a]", setup=setup_string, number=10000)
0.003599141953657181
>>> setup_string = "from collections import OrderedDict\n"
>>> setup_string += "a = OrderedDict({1:89, 2:3, 3:0, 4:5})\n"
>>> setup_string += "b = a.items()"
>>> timeit.timeit(stmt="[(k, val) for k, val in b]", setup=setup_string, number=10000)
0.003581275490432745
回答 22
from operator import itemgetter
# if you would like to play with multiple dictionaries then here you go:# Three dictionaries that are composed of first name and last name.
user =[{'fname':'Mo','lname':'Mahjoub'},{'fname':'Abdo','lname':'Al-hebashi'},{'fname':'Ali','lname':'Muhammad'}]# This loop will sort by the first and the last names.# notice that in a dictionary order doesn't matter. So it could put the first name first or the last name first. for k in sorted (user, key=itemgetter ('fname','lname')):print(k)# This one will sort by the first name only.for x in sorted (user, key=itemgetter ('fname')):print(x)
from operator import itemgetter
# if you would like to play with multiple dictionaries then here you go:
# Three dictionaries that are composed of first name and last name.
user = [
{'fname': 'Mo', 'lname': 'Mahjoub'},
{'fname': 'Abdo', 'lname': 'Al-hebashi'},
{'fname': 'Ali', 'lname': 'Muhammad'}
]
# This loop will sort by the first and the last names.
# notice that in a dictionary order doesn't matter. So it could put the first name first or the last name first.
for k in sorted (user, key=itemgetter ('fname', 'lname')):
print (k)
# This one will sort by the first name only.
for x in sorted (user, key=itemgetter ('fname')):
print (x)
回答 23
dictionary ={1:[2],2:[],5:[4,5],4:[5],3:[1]}
temp=sorted(dictionary)
sorted_dict = dict([(k,dictionary[k])for i,k in enumerate(temp)])
sorted_dict:{1:[2],2:[],3:[1],4:[5],5:[4,5]}
My suggestion is this as it allows you to sort a dict or keep a dict sorted as you are adding items and might need to add items in the future:
Build a dict from scratch as you go along. Have a second data structure, a list, with your list of keys. The bisect package has an insort function which allows inserting into a sorted list, or sort your list after completely populating your dict. Now, when you iterate over your dict, you instead iterate over the list to access each key in an in-order fashion without worrying about the representation of the dict structure (which was not made for sorting).
回答 26
l = dict.keys()
l2 = l
l2.append(0)
l3 =[]for repeater in range(0, len(l)):
smallnum = float("inf")for listitem in l2:if listitem < smallnum:
smallnum = listitem
l2.remove(smallnum)
l3.append(smallnum)
l3.remove(0)
l = l3
for listitem in l:print(listitem)
l = dict.keys()
l2 = l
l2.append(0)
l3 = []
for repeater in range(0, len(l)):
smallnum = float("inf")
for listitem in l2:
if listitem < smallnum:
smallnum = listitem
l2.remove(smallnum)
l3.append(smallnum)
l3.remove(0)
l = l3
for listitem in l:
print(listitem)
I need to sort the list by number of counts descending.
I’ve seen several methods for this, but I’m looking for best practice in Python.
回答 0
# To sort the list in place...
ut.sort(key=lambda x: x.count, reverse=True)# To return a new list, use the sorted() built-in function...
newlist = sorted(ut, key=lambda x: x.count, reverse=True)
# To sort the list in place...
ut.sort(key=lambda x: x.count, reverse=True)
# To return a new list, use the sorted() built-in function...
newlist = sorted(ut, key=lambda x: x.count, reverse=True)
try:import operator
exceptImportError: keyfun=lambda x: x.count # use a lambda if no operator moduleelse: keyfun= operator.attrgetter("count")# use operator since it's faster than lambda
ut.sort(key=keyfun, reverse=True)# sort in-place
A way that can be fastest, especially if your list has a lot of records, is to use operator.attrgetter("count"). However, this might run on an pre-operator version of Python, so it would be nice to have a fallback mechanism. You might want to do the following, then:
try: import operator
except ImportError: keyfun= lambda x: x.count # use a lambda if no operator module
else: keyfun= operator.attrgetter("count") # use operator since it's faster than lambda
ut.sort(key=keyfun, reverse=True) # sort in-place
回答 2
读者应注意,key =方法:
ut.sort(key=lambda x: x.count, reverse=True)
比向对象添加丰富的比较运算符快许多倍。我很惊讶地阅读了这篇文章(“ Python in a Nutshell”的第485页)。您可以通过在这个小程序上运行测试来确认这一点:
#!/usr/bin/env pythonimport random
class C:def __init__(self,count):
self.count = count
def __cmp__(self,other):return cmp(self.count,other.count)
longList =[C(random.random())for i in xrange(1000000)]#about 6.1 secs
longList2 = longList[:]
longList.sort()#about 52 - 6.1 = 46 secs
longList2.sort(key =lambda c: c.count)#about 9 - 6.1 = 3 secs
is many times faster than adding rich comparison operators to the objects. I was surprised to read this (page 485 of “Python in a Nutshell”). You can confirm this by running tests on this little program:
#!/usr/bin/env python
import random
class C:
def __init__(self,count):
self.count = count
def __cmp__(self,other):
return cmp(self.count,other.count)
longList = [C(random.random()) for i in xrange(1000000)] #about 6.1 secs
longList2 = longList[:]
longList.sort() #about 52 - 6.1 = 46 secs
longList2.sort(key = lambda c: c.count) #about 9 - 6.1 = 3 secs
My, very minimal, tests show the first sort is more than 10 times slower, but the book says it is only about 5 times slower in general. The reason they say is due to the highly optimizes sort algorithm used in python (timsort).
Still, its very odd that .sort(lambda) is faster than plain old .sort(). I hope they fix that.
It’s good practice to make object sorting logic, if applicable, a property of the class rather than incorporated in each instance the ordering is required.
This ensures consistency and removes the need for boilerplate code.
At a minimum, you should specify __eq__ and __lt__ operations for this to work. Then just use sorted(list_of_objects).
class Card(object):
def __init__(self, rank, suit):
self.rank = rank
self.suit = suit
def __eq__(self, other):
return self.rank == other.rank and self.suit == other.suit
def __lt__(self, other):
return self.rank < other.rank
hand = [Card(10, 'H'), Card(2, 'h'), Card(12, 'h'), Card(13, 'h'), Card(14, 'h')]
hand_order = [c.rank for c in hand] # [10, 2, 12, 13, 14]
hand_sorted = sorted(hand)
hand_sorted_order = [c.rank for c in hand_sorted] # [2, 10, 12, 13, 14]
回答 4
from operator import attrgetter
ut.sort(key = attrgetter('count'), reverse =True)
I have some data either in a list of lists or a list of tuples, like this:
data = [[1,2,3], [4,5,6], [7,8,9]]
data = [(1,2,3), (4,5,6), (7,8,9)]
And I want to sort by the 2nd element in the subset. Meaning, sorting by 2,5,8 where 2 is from (1,2,3), 5 is from (4,5,6). What is the common way to do this? Should I store tuples or lists in my list?
I just want to add to Stephen’s answer if you want to sort the array from high to low, another way other than in the comments above is just to add this to the line:
>>>from operator import itemgetter
>>>from numpy.random import randint
>>> values = randint(0,9,30000).reshape((10000,3))>>> tpls =[tuple(values[i,:])for i in range(len(values))]>>> tpls[:5]# display sample from list[(1,0,0),(8,5,5),(5,4,0),(5,7,7),(4,2,1)]>>> sorted(tpls[:5], key=itemgetter(1))# example sort[(1,0,0),(4,2,1),(5,4,0),(8,5,5),(5,7,7)]>>>%timeit sorted(tpls, key=itemgetter(1))100 loops, best of 3:4.89 ms per loop
>>>%timeit sorted(tpls, key=lambda tup: tup[1])100 loops, best of 3:6.39 ms per loop
>>>%timeit sorted(tpls, key=(itemgetter(1,0)))100 loops, best of 3:16.1 ms per loop
>>>%timeit sorted(tpls, key=lambda tup:(tup[1], tup[0]))100 loops, best of 3:17.1 ms per loop
key is a function that will be called to transform the collection’s items for comparison.. like compareTo method in Java.
The parameter passed to key must be something that is callable. Here, the use of lambda creates an anonymous function (which is a callable).
The syntax of lambda is the word lambda followed by a iterable name then a single block of code.
Below example, we are sorting a list of tuple that holds the info abt time of certain event and actor name.
We are sorting this list by time of event occurrence – which is the 0th element of a tuple.
Note – s.sort([cmp[, key[, reverse]]]) sorts the items of s in place
It is rather hackish, since it relies on converting the values into a single string representation for comparison, but it works as expected for numbers including negative ones (although you will need to format your string appropriately with zero paddings if you are using numbers)
‘key’ is used to sort by an arbitrary value and ‘itemgetter’ sets that value to each item’s ‘name’ attribute.
回答 5
a =[{'name':'Homer','age':39},...]# This changes the list a
a.sort(key=lambda k : k['name'])# This returns a new list (a is not modified)
sorted(a, key=lambda k : k['name'])
a = [{'name':'Homer', 'age':39}, ...]
# This changes the list a
a.sort(key=lambda k : k['name'])
# This returns a new list (a is not modified)
sorted(a, key=lambda k : k['name'])
You could use a custom comparison function, or you could pass in a function that calculates a custom sort key. That’s usually more efficient as the key is only calculated once per item, while the comparison function would be called many more times.
In computer science, the Schwartzian transform is a Perl programming
idiom used to improve the efficiency of sorting a list of items. This
idiom is appropriate for comparison-based sorting when the ordering is
actually based on the ordering of a certain property (the key) of the
elements, where computing that property is an intensive operation that
should be performed a minimal number of times. The Schwartzian
Transform is notable in that it does not use named temporary arrays.
def sort_key_func(item):""" helper function used to sort list of dicts
:param item: dict
:return: sorted list of tuples (k, v)
"""
pairs =[]for k, v in item.items():
pairs.append((k, v))return sorted(pairs)
sorted(A, key=sort_key_func)
Here is the alternative general solution – it sorts elements of dict by keys and values.
The advantage of it – no need to specify keys, and it would still work if some keys are missing in some of dictionaries.
def sort_key_func(item):
""" helper function used to sort list of dicts
:param item: dict
:return: sorted list of tuples (k, v)
"""
pairs = []
for k, v in item.items():
pairs.append((k, v))
return sorted(pairs)
sorted(A, key=sort_key_func)
If you need the original list, call the sorted() function passing it the list and the key function, then assign the returned sorted list to a new variable:
import random
import operator
# create a list of 100 dicts with random 8-letter names and random ages from 0 to 100.
l =[{'name':''.join(random.choices(string.ascii_lowercase, k=8)),'age': random.randint(0,100)}for i in range(100)]# Test the performance with a lambda function sorting on name%timeit sorted(l, key=lambda x: x['name'])13µs ±388 ns per loop (mean ± std. dev. of 7 runs,100000 loops each)# Test the performance with itemgetter sorting on name%timeit sorted(l, key=operator.itemgetter('name'))10.7µs ±38.1 ns per loop (mean ± std. dev. of 7 runs,100000 loops each)# Check that each technique produces same sort order
sorted(l, key=lambda x: x['name'])== sorted(l, key=operator.itemgetter('name'))True
If performance is a concern, I would use operator.itemgetter instead of lambda as built-in functions perform faster than hand-crafted functions. The itemgetter function seems to perform approximately 20% faster than lambda based on my testing.
Likewise, the builtin functions run faster than hand-built equivalents. For example, map(operator.add, v1, v2) is faster than map(lambda x,y: x+y, v1, v2).
Here is a comparison of sorting speed using lambda vs itemgetter.
import random
import operator
# create a list of 100 dicts with random 8-letter names and random ages from 0 to 100.
l = [{'name': ''.join(random.choices(string.ascii_lowercase, k=8)), 'age': random.randint(0, 100)} for i in range(100)]
# Test the performance with a lambda function sorting on name
%timeit sorted(l, key=lambda x: x['name'])
13 µs ± 388 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
# Test the performance with itemgetter sorting on name
%timeit sorted(l, key=operator.itemgetter('name'))
10.7 µs ± 38.1 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
# Check that each technique produces same sort order
sorted(l, key=lambda x: x['name']) == sorted(l, key=operator.itemgetter('name'))
True
Both techniques sort the list in the same order (verified by execution of the final statement in the code block) but one is a little faster.
回答 17
您可以使用以下代码
sorted_dct = sorted(dct_name.items(), key =lambda x : x[1])
I have a dictionary of values read from two fields in a database: a string field and a numeric field. The string field is unique, so that is the key of the dictionary.
I can sort on the keys, but how can I sort based on the values?
Note: I have read Stack Overflow question here How do I sort a list of dictionaries by a value of the dictionary? and probably could change my code to have a list of dictionaries, but since I do not really need a list of dictionaries I wanted to know if there is a simpler solution to sort either in ascending or descending order.
回答 0
Python 3.6+
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}
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}
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.
Well, it is actually possible to do a “sort by dictionary values”. Recently I had to do that in a Code Golf (Stack Overflow question Code golf: Word frequency chart). Abridged, the problem was of the kind: given a text, count how often each word is encountered and display a list of the top words, sorted by decreasing frequency.
If you construct a dictionary with the words as keys and the number of occurrences of each word as value, simplified here as:
from collections import defaultdict
d = defaultdict(int)
for w in text.split():
d[w] += 1
then you can get a list of the words, ordered by frequency of use with sorted(d, key=d.get) – the sort iterates over the dictionary keys, using the number of word occurrences as a sort key .
for w in sorted(d, key=d.get, reverse=True):
print(w, d[w])
I am writing this detailed explanation to illustrate what people often mean by “I can easily sort a dictionary by key, but how do I sort by value” – and I think the original post was trying to address such an issue. And the solution is to do sort of list of the keys, based on the values, as shown above.
>>> d ={"third":3,"first":1,"fourth":4,"second":2}>>>for k, v in d.items():...print"%s: %s"%(k, v)...
second:2
fourth:4
third:3
first:1>>> d{'second':2,'fourth':4,'third':3,'first':1}
Whilst I found the accepted answer useful, I was also surprised that it hasn’t been updated to reference OrderedDict from the standard library collections module as a viable, modern alternative – designed to solve exactly this type of problem.
It can often be very handy to use namedtuple. For example, you have a dictionary of ‘name’ as keys and ‘score’ as values and you want to sort on ‘score’:
import collections
Player = collections.namedtuple('Player', 'score name')
d = {'John':5, 'Alex':10, 'Richard': 7}
sorting with lowest score first:
worst = sorted(Player(v,k) for (k,v) in d.items())
sorting with highest score first:
best = sorted([Player(v,k) for (k,v) in d.items()], reverse=True)
Now you can get the name and score of, let’s say the second-best player (index=1) very Pythonically like this:
player = best[1]
player.name
'Richard'
player.score
7
As of Python 3.6 the built-in dict will be ordered
Good news, so the OP’s original use case of mapping pairs retrieved from a database with unique string ids as keys and numeric values as values into a built-in Python v3.6+ dict, should now respect the insert order.
If say the resulting two column table expressions from a database query like:
SELECT a_key, a_value FROM a_table ORDER BY a_value;
would be stored in two Python tuples, k_seq and v_seq (aligned by numerical index and with the same length of course), then:
Hopefully this will lead to a thin layer OrderedDict implementation as a first step. As @JimFasarakis-Hilliard indicated, some see use cases for the OrderedDict type also in the future. I think the Python community at large will carefully inspect, if this will stand the test of time, and what the next steps will be.
Time to rethink our coding habits to not miss the possibilities opened by stable ordering of:
Keyword arguments and
(intermediate) dict storage
The first because it eases dispatch in the implementation of functions and methods in some cases.
The second as it encourages to more easily use dicts as intermediate storage in processing pipelines.
Raymond Hettinger kindly provided documentation explaining “The Tech Behind Python 3.6 Dictionaries” – from his San Francisco Python Meetup Group presentation 2016-DEC-08.
And maybe quite some Stack Overflow high decorated question and answer pages will receive variants of this information and many high quality answers will require a per version update too.
Caveat Emptor (but also see below update 2017-12-15):
As @ajcr rightfully notes: “The order-preserving aspect of this new implementation is considered an implementation detail and should not be relied upon.” (from the whatsnew36) not nit picking, but the citation was cut a bit pessimistic ;-). It continues as ” (this may change in the future, but it is desired to have this new dict implementation in the language for a few releases before changing the language spec to mandate order-preserving semantics for all current and future Python implementations; this also helps preserve backwards-compatibility with older versions of the language where random iteration order is still in effect, e.g. Python 3.5).”
So as in some human languages (e.g. German), usage shapes the language, and the will now has been declared … in whatsnew36.
Make it so. “Dict keeps insertion order” is the ruling. Thanks!
So, the version 3.6 CPython side-effect of dict insertion ordering is now becoming part of the language spec (and not anymore only an implementation detail). That mail thread also surfaced some distinguishing design goals for collections.OrderedDict as reminded by Raymond Hettinger during discussion.
回答 9
我有同样的问题,我这样解决了:
WantedOutput= sorted(MyDict, key=lambda x :MyDict[x])
I had the same problem, and I solved it like this:
WantedOutput = sorted(MyDict, key=lambda x : MyDict[x])
(People who answer “It is not possible to sort a dict” did not read the question! In fact, “I can sort on the keys, but how can I sort based on the values?” clearly means that he wants a list of the keys sorted according to the value of their values.)
Please notice that the order is not well defined (keys with the same value will be in an arbitrary order in the output list).
>>> x ={1:2,3:4,4:3,2:1,0:0}>>>from collections importCounter>>>#To sort in reverse order>>>Counter(x).most_common()[(3,4),(4,3),(1,2),(2,1),(0,0)]>>>#To sort in ascending order>>>Counter(x).most_common()[::-1][(0,0),(2,1),(1,2),(4,3),(3,4)]>>>#To get a dictionary sorted by values>>>from collections importOrderedDict>>>OrderedDict(Counter(x).most_common()[::-1])OrderedDict([(0,0),(2,1),(1,2),(4,3),(3,4)])
from django.utils.datastructures importSortedDictdef sortedDictByKey(self,data):"""Sorted dictionary order by key"""
sortedDict =SortedDict()if data:if isinstance(data, dict):
sortedKey = sorted(data.keys())for k in sortedKey:
sortedDict[k]= data[k]return sortedDict
from django.utils.datastructures import SortedDict
def sortedDictByKey(self,data):
"""Sorted dictionary order by key"""
sortedDict = SortedDict()
if data:
if isinstance(data, dict):
sortedKey = sorted(data.keys())
for k in sortedKey:
sortedDict[k] = data[k]
return sortedDict
As pointed out by Dilettant, Python 3.6 will now keep the order! I thought I’d share a function I wrote that eases the sorting of an iterable (tuple, list, dict). In the latter case, you can sort either on keys or values, and it can take numeric comparison into account. Only for >= 3.6!
When you try using sorted on an iterable that holds e.g. strings as well as ints, sorted() will fail. Of course you can force string comparison with str(). However, in some cases you want to do actual numeric comparison where 12 is smaller than 20 (which is not the case in string comparison). So I came up with the following. When you want explicit numeric comparison you can use the flag num_as_num which will try to do explicit numeric sorting by trying to convert all values to floats. If that succeeds, it will do numeric sorting, otherwise it’ll resort to string comparison.
def gen(originalDict):for x, y in sorted(zip(originalDict.keys(), originalDict.values()), key=lambda z: z[1]):yield(x, y)#Yields as a tuple with (key, value). You can iterate with conditional clauses to get what you want. for bleh, meh in gen(myDict):if bleh =="foo":print(myDict[bleh])
Of course, remember, you need to use OrderedDict because regular Python dictionaries don’t keep the original order.
from collections import OrderedDict
a = OrderedDict(sorted(originalDict.items(), key=lambda x: x[1]))
If you do not have Python 2.7 or higher, the best you can do is iterate over the values in a generator function. (There is an OrderedDict for 2.4 and 2.6 here, but
a) I don’t know about how well it works
and
b) You have to download and install it of course. If you do not have administrative access, then I’m afraid the option’s out.)
def gen(originalDict):
for x, y in sorted(zip(originalDict.keys(), originalDict.values()), key=lambda z: z[1]):
yield (x, y)
#Yields as a tuple with (key, value). You can iterate with conditional clauses to get what you want.
for bleh, meh in gen(myDict):
if bleh == "foo":
print(myDict[bleh])
You can also print out every value
for bleh, meh in gen(myDict):
print(bleh, meh)
Please remember to remove the parentheses after print if not using Python 3.0 or above
from dicts.sorteddict importValueSortedDict
d ={1:2,3:4,4:3,2:1,0:0}
sorted_dict =ValueSortedDict(d)print sorted_dict.items()[(0,0),(2,1),(1,2),(4,3),(3,4)]
#Assume dictionary to be:
d ={'apple':500.1,'banana':1500.2,'orange':1.0,'pineapple':789.0}# create a temporary list
tmp =[]# iterate through the dictionary and append each tuple into the temporary list for key, value in d.items():
tmptuple =(value, key)
tmp.append(tmptuple)# sort the list in ascending order
tmp = sorted(tmp)print(tmp)
如果要按降序对列表进行排序,只需将原始排序行更改为:
tmp = sorted(tmp, reverse=True)
使用列表推导,一个衬里将是:
#Assuming the dictionary looks like
d ={'apple':500.1,'banana':1500.2,'orange':1.0,'pineapple':789.0}#One liner for sorting in ascending orderprint(sorted([(v, k)for k, v in d.items()]))#One liner for sorting in descending orderprint(sorted([(v, k)for k, v in d.items()], reverse=True))
You may use a temporary list to help you to sort the dictionary:
#Assume dictionary to be:
d = {'apple': 500.1, 'banana': 1500.2, 'orange': 1.0, 'pineapple': 789.0}
# create a temporary list
tmp = []
# iterate through the dictionary and append each tuple into the temporary list
for key, value in d.items():
tmptuple = (value, key)
tmp.append(tmptuple)
# sort the list in ascending order
tmp = sorted(tmp)
print (tmp)
If you want to sort the list in descending order, simply change the original sorting line to:
tmp = sorted(tmp, reverse=True)
Using list comprehension, the one liner would be:
#Assuming the dictionary looks like
d = {'apple': 500.1, 'banana': 1500.2, 'orange': 1.0, 'pineapple': 789.0}
#One liner for sorting in ascending order
print (sorted([(v, k) for k, v in d.items()]))
#One liner for sorting in descending order
print (sorted([(v, k) for k, v in d.items()], reverse=True))
Sample Output:
#Asending order
[(1.0, 'orange'), (500.1, 'apple'), (789.0, 'pineapple'), (1500.2, 'banana')]
#Descending order
[(1500.2, 'banana'), (789.0, 'pineapple'), (500.1, 'apple'), (1.0, 'orange')]
回答 26
遍历字典并按其值降序对其进行排序:
$ python --version
Python3.2.2
$ cat sort_dict_by_val_desc.py
dictionary = dict(siis =1, sana =2, joka =3, tuli =4, aina =5)for word in sorted(dictionary, key=dictionary.get, reverse=True):print(word, dictionary[word])
$ python sort_dict_by_val_desc.py
aina 5
tuli 4
joka 3
sana 2
siis 1
Iterate through a dict and sort it by its values in descending order:
$ python --version
Python 3.2.2
$ cat sort_dict_by_val_desc.py
dictionary = dict(siis = 1, sana = 2, joka = 3, tuli = 4, aina = 5)
for word in sorted(dictionary, key=dictionary.get, reverse=True):
print(word, dictionary[word])
$ python sort_dict_by_val_desc.py
aina 5
tuli 4
joka 3
sana 2
siis 1
If your values are integers, and you use Python 2.7 or newer, you can use collections.Counter instead of dict. The most_common method will give you all items, sorted by the value.
Because of requirements to retain backward compatability with older versions of Python I think the OrderedDict solution is very unwise. You want something that works with Python 2.7 and older versions.
But the collections solution mentioned in another answer is absolutely superb, because you retrain a connection between the key and value which in the case of dictionaries is extremely important.
I don’t agree with the number one choice presented in another answer, because it throws away the keys.
I used the solution mentioned above (code shown below) and retained access to both keys and values and in my case the ordering was on the values, but the importance was the ordering of the keys after ordering the values.
from collections import Counter
x = {'hello':1, 'python':5, 'world':3}
c=Counter(x)
print c.most_common()
>> [('python', 5), ('world', 3), ('hello', 1)]