我有一个从数据库中读取的键值对字典:一个字符串字段和一个数字字段。字符串字段是唯一的,所以它是字典的键。
我可以按照键排序,但是如何基于值排序呢?
注意:我已经在Stack Overflow上阅读了这里的问题:How do I sort a list of dictionaries by a value of the dictionary?,并且可能可以更改我的代码以使用字典列表,但由于我实际上不需要字典列表,我想知道是否有更简单的解决方案来升序或降序排序。
我有一个从数据库中读取的键值对字典:一个字符串字段和一个数字字段。字符串字段是唯一的,所以它是字典的键。
我可以按照键排序,但是如何基于值排序呢?
注意:我已经在Stack Overflow上阅读了这里的问题:How do I sort a list of dictionaries by a value of the dictionary?,并且可能可以更改我的代码以使用字典列表,但由于我实际上不需要字典列表,我想知道是否有更简单的解决方案来升序或降序排序。
当然,记住,你需要使用OrderedDict
,因为普通的Python字典不能保持原始顺序。
from collections import OrderedDict
a = OrderedDict(sorted(originalDict.items(), key=lambda x: x[1]))
如果您没有 Python 2.7 或更高版本,则最好的方法是迭代生成器函数中的值。(这里有一个用于 2.4 和 2.6 的 OrderedDict
,链接在这里,但是 a) 我不知道它的表现如何,以及 b) 您需要下载并安装它。如果您没有管理员权限,则恐怕这个选项不可行。)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])
您也可以打印出每个值。for bleh, meh in gen(myDict):
print(bleh, meh)
请记得在使用Python 3.0或更高版本之外的版本时,删除print后面的括号。以下是使用 d.values()
和 d.keys()
在字典上运用zip的解决方法。在这个链接的几行代码下面(关于 字典视图对象),有以下内容:
这个方法可以使用zip()创建(value, key)对: pairs = zip(d.values(), d.keys())。
我们可以按照以下方式操作:
d = {'key1': 874.7, 'key2': 5, 'key3': 8.1}
d_sorted = sorted(zip(d.values(), d.keys()))
print d_sorted
# prints: [(5, 'key2'), (8.1, 'key3'), (874.7, 'key1')]
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
正如Dilettant所指出的,Python 3.6现在会保留顺序!我想分享一个我编写的函数,可以简化对可迭代对象(元组、列表、字典)进行排序的过程。在后一种情况下,您可以按键或值进行排序,并且它可以考虑数值比较。仅适用于 >= 3.6版本!
当您尝试使用sorted()对包含字符串和整数等不同类型的元素的可迭代对象进行排序时,sorted()会失败。当然,您可以通过str()强制使用字符串比较。但是,在某些情况下,您希望进行实际的数字比较,其中12
小于20
(这在字符串比较中不是这样的)。因此,我想到了以下解决方案。当您需要明确的数字比较时,可以使用标志num_as_num
,它将尝试将所有值转换为浮点数来进行显式的数字排序。如果成功,则进行数字排序,否则将回归到字符串比较。
欢迎提出改进意见。
def sort_iterable(iterable, sort_on=None, reverse=False, num_as_num=False):
def _sort(i):
# sort by 0 = keys, 1 values, None for lists and tuples
try:
if num_as_num:
if i is None:
_sorted = sorted(iterable, key=lambda v: float(v), reverse=reverse)
else:
_sorted = dict(sorted(iterable.items(), key=lambda v: float(v[i]), reverse=reverse))
else:
raise TypeError
except (TypeError, ValueError):
if i is None:
_sorted = sorted(iterable, key=lambda v: str(v), reverse=reverse)
else:
_sorted = dict(sorted(iterable.items(), key=lambda v: str(v[i]), reverse=reverse))
return _sorted
if isinstance(iterable, list):
sorted_list = _sort(None)
return sorted_list
elif isinstance(iterable, tuple):
sorted_list = tuple(_sort(None))
return sorted_list
elif isinstance(iterable, dict):
if sort_on == 'keys':
sorted_dict = _sort(0)
return sorted_dict
elif sort_on == 'values':
sorted_dict = _sort(1)
return sorted_dict
elif sort_on is not None:
raise ValueError(f"Unexpected value {sort_on} for sort_on. When sorting a dict, use key or values")
else:
raise TypeError(f"Unexpected type {type(iterable)} for iterable. Expected a list, tuple, or dict")
我刚从Python for Everybody学到了一项相关技能。
你可以使用一个临时列表来帮助你对字典进行排序:
# 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 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))
输出示例:
# Ascending 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')]
使用来自dicts的ValueSortedDict:
from dicts.sorteddict import ValueSortedDict
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)]
遍历字典并按其值降序排序:
$ 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
这在3.1.x版本中有效:
import operator
slovar_sorted=sorted(slovar.items(), key=operator.itemgetter(1), reverse=True)
print(slovar_sorted)
为了完整起见,我将发布一种使用heapq的解决方案。请注意,此方法适用于数值和非数值。
>>> x = {1: 2, 3: 4, 4:3, 2:1, 0:0}
>>> x_items = x.items()
>>> heapq.heapify(x_items)
>>> #To sort in reverse order
>>> heapq.nlargest(len(x_items),x_items, operator.itemgetter(1))
[(3, 4), (4, 3), (1, 2), (2, 1), (0, 0)]
>>> #To sort in ascending order
>>> heapq.nsmallest(len(x_items),x_items, operator.itemgetter(1))
[(0, 0), (2, 1), (1, 2), (4, 3), (3, 4)]