我有一个从数据库中两个字段读取的值字典:字符串字段和数字字段。字符串字段是唯一的,因此它是字典的关键字。
我可以按关键字排序,但如何根据值排序?
注意:我在这里读过堆栈溢出问题。如何根据字典的值对字典列表进行排序?并且可能会更改我的代码,使其具有字典列表,但由于我确实不需要字典列表,我想知道是否有更简单的解决方案来按升序或降序排序。
我有一个从数据库中两个字段读取的值字典:字符串字段和数字字段。字符串字段是唯一的,因此它是字典的关键字。
我可以按关键字排序,但如何根据值排序?
注意:我在这里读过堆栈溢出问题。如何根据字典的值对字典列表进行排序?并且可能会更改我的代码,使其具有字典列表,但由于我确实不需要字典列表,我想知道是否有更简单的解决方案来按升序或降序排序。
当前回答
正如Dilettant所指出的,Python 3.6现在将保持秩序!我想我应该分享我编写的一个函数,它简化了可迭代(元组、列表、dict)的排序。在后一种情况下,可以对键或值进行排序,并且可以考虑数值比较。仅适用于>=3.6!
当您尝试在包含字符串和int的可迭代对象上使用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")
其他回答
months = {"January": 31, "February": 28, "March": 31, "April": 30, "May": 31,
"June": 30, "July": 31, "August": 31, "September": 30, "October": 31,
"November": 30, "December": 31}
def mykey(t):
""" Customize your sorting logic using this function. The parameter to
this function is a tuple. Comment/uncomment the return statements to test
different logics.
"""
return t[1] # sort by number of days in the month
#return t[1], t[0] # sort by number of days, then by month name
#return len(t[0]) # sort by length of month name
#return t[0][-1] # sort by last character of month name
# Since a dictionary can't be sorted by value, what you can do is to convert
# it into a list of tuples with tuple length 2.
# You can then do custom sorts by passing your own function to sorted().
months_as_list = sorted(months.items(), key=mykey, reverse=False)
for month in months_as_list:
print month
正如Dilettant所指出的,Python 3.6现在将保持秩序!我想我应该分享我编写的一个函数,它简化了可迭代(元组、列表、dict)的排序。在后一种情况下,可以对键或值进行排序,并且可以考虑数值比较。仅适用于>=3.6!
当您尝试在包含字符串和int的可迭代对象上使用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")
在最近的Python2.7中,我们有了新的OrderedDict类型,它可以记住添加项目的顺序。
>>> 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}
要从原始字典创建新的有序字典,请按值排序:
>>> from collections import OrderedDict
>>> d_sorted_by_value = OrderedDict(sorted(d.items(), key=lambda x: x[1]))
OrderedDict的行为类似于普通dict:
>>> for k, v in d_sorted_by_value.items():
... print "%s: %s" % (k, v)
...
first: 1
second: 2
third: 3
fourth: 4
>>> d_sorted_by_value
OrderedDict([('first': 1), ('second': 2), ('third': 3), ('fourth': 4)])
如果您的值是整数,并且使用Python 2.7或更高版本,则可以使用collections.Counter而不是dict。most_common方法将为您提供按值排序的所有项。
您还可以使用可以传递给参数键的自定义函数。
def dict_val(x):
return x[1]
x = {1: 2, 3: 4, 4: 3, 2: 1, 0: 0}
sorted_x = sorted(x.items(), key=dict_val)