python:如何按字典值对字典列表进行排序?

python:如何按字典值对字典列表进行排序?

我有一个字典列表,希望每个条目都按照特定的属性值排序。

考虑到下面的数组,

1
[{'name':'Homer', 'age':39}, {'name':'Bart', 'age':10}]

当按name排序时,应该变成

1
[{'name':'Bart', 'age':10}, {'name':'Homer', 'age':39}]

它可能看起来更干净使用一个关键而不是一个cmp:

1
newlist = sorted(list_to_be_sorted, key=lambda k: k['name'])

或作为参考塞巴斯蒂安和其他人认为,

1
2
from operator import itemgetter
newlist = sorted(list_to_be_sorted, key=itemgetter('name'))

为了完整性(正如fitzgeraldsteele在评论中指出的),添加reverse=True来降序排序

1
newlist = sorted(l, key=itemgetter('name'), reverse=True)

1
import operator

按key='name'对字典列表进行排序:

1
list_of_dicts.sort(key=operator.itemgetter('name'))

按key='age'对字典列表进行排序:

1
list_of_dicts.sort(key=operator.itemgetter('age'))


如果你想按多个键对列表排序,你可以这样做:

1
2
my_list = [{'name':'Homer', 'age':39}, {'name':'Milhouse', 'age':10}, {'name':'Bart', 'age':10} ]
sortedlist = sorted(my_list , key=lambda elem:"%02d %s" % (elem['age'], elem['name']))

这是相当笨拙的,因为它依赖于将值转换为单个字符串表示来进行比较,但是对于包括负数在内的数字,它的工作方式与预期的一样(尽管如果使用数字,则需要使用零划片适当地格式化字符串)


1
2
3
my_list = [{'name':'Homer', 'age':39}, {'name':'Bart', 'age':10}]

my_list.sort(lambda x,y : cmp(x['name'], y['name']))

my_list现在将是您想要的。

(3年后)编辑后添加:

新的key参数更有效、更简洁。一个更好的答案是:

1
my_list = sorted(my_list, key=lambda k: k['name'])

…在我看来,lambda比operator.itemgetter更容易理解,但是YMMV。


1
2
import operator
a_list_of_dicts.sort(key=operator.itemgetter('name'))

'key'用于按任意值排序,'itemgetter'将该值设置为每个项目的'name'属性。


我想你的意思是:

1
[{'name':'Homer', 'age':39}, {'name':'Bart', 'age':10}]

这样排序:

1
sorted(l,cmp=lambda x,y: cmp(x['name'],y['name']))


使用Perl中的Schwartzian转换,

1
py = [{'name':'Homer', 'age':39}, {'name':'Bart', 'age':10}]

1
2
3
4
sort_on ="name"
decorated = [(dict_[sort_on], dict_) for dict_ in py]
decorated.sort()
result = [dict_ for (key, dict_) in decorated]

给了

1
2
>>> result
[{'age': 10, 'name': 'Bart'}, {'age': 39, 'name': 'Homer'}]

更多关于Perl Schwartzian转换的信息

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.


1
2
3
4
5
6
7
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'])

您可以使用自定义比较函数,也可以传入计算自定义排序键的函数。这通常更有效,因为每个项只计算一次键值,而比较函数将被调用多次。

你可以这样做:

1
2
3
def mykey(adict): return adict['name']
x = [{'name': 'Homer', 'age': 39}, {'name': 'Bart', 'age':10}]
sorted(x, key=mykey)

但是标准库包含一个获取任意对象项的通用例程:itemgetter。所以试试这个:

1
2
3
from operator import itemgetter
x = [{'name': 'Homer', 'age': 39}, {'name': 'Bart', 'age':10}]
sorted(x, key=itemgetter('name'))

您必须实现自己的比较函数,该函数将根据名称键的值比较字典。参见如何从PythonInfo Wiki中排序


我试着这样做:

1
my_list.sort(key=lambda x: x['name'])

它也适用于整数。


这是另一种通用解决方案——它根据键和值对dict的元素进行排序。它的优点——不需要指定键,而且如果某些字典中缺少一些键,它仍然可以工作。

1
2
3
4
5
6
7
8
9
10
11
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)

有时候我们需要使用lower()作为例子

1
2
3
4
5
6
7
8
9
10
11
lists = [{'name':'Homer', 'age':39},
  {'name':'Bart', 'age':10},
  {'name':'abby', 'age':9}]

lists = sorted(lists, key=lambda k: k['name'])
print(lists)
# [{'name':'Bart', 'age':10}, {'name':'Homer', 'age':39}, {'name':'abby', 'age':9}]

lists = sorted(lists, key=lambda k: k['name'].lower())
print(lists)
# [ {'name':'abby', 'age':9}, {'name':'Bart', 'age':10}, {'name':'Homer', 'age':39}]

使用panda包是另一种方法,尽管它在大规模运行时比其他人提出的更传统的方法慢得多:

1
2
3
4
5
6
import pandas as pd

listOfDicts = [{'name':'Homer', 'age':39}, {'name':'Bart', 'age':10}]
df = pd.DataFrame(listOfDicts)
df = df.sort_values('name')
sorted_listOfDicts = df.T.to_dict().values()

下面是一个小列表和一个大的(100k+) dicts列表的一些基准值:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
setup_large ="listOfDicts = [];\
[listOfDicts.extend(({'name':'Homer', 'age':39}, {'name':'Bart', 'age':10})) for _ in range(50000)];\
from operator import itemgetter;import pandas as pd;\
df = pd.DataFrame(listOfDicts);"


setup_small ="listOfDicts = [];\
listOfDicts.extend(({'name':'Homer', 'age':39}, {'name':'Bart', 'age':10}));\
from operator import itemgetter;import pandas as pd;\
df = pd.DataFrame(listOfDicts);"


method1 ="newlist = sorted(listOfDicts, key=lambda k: k['name'])"
method2 ="newlist = sorted(listOfDicts, key=itemgetter('name'))"
method3 ="df = df.sort_values('name');\
sorted_listOfDicts = df.T.to_dict().values()"


import timeit
t = timeit.Timer(method1, setup_small)
print('Small Method LC: ' + str(t.timeit(100)))
t = timeit.Timer(method2, setup_small)
print('Small Method LC2: ' + str(t.timeit(100)))
t = timeit.Timer(method3, setup_small)
print('Small Method Pandas: ' + str(t.timeit(100)))

t = timeit.Timer(method1, setup_large)
print('Large Method LC: ' + str(t.timeit(100)))
t = timeit.Timer(method2, setup_large)
print('Large Method LC2: ' + str(t.timeit(100)))
t = timeit.Timer(method3, setup_large)
print('Large Method Pandas: ' + str(t.timeit(1)))

#Small Method LC: 0.000163078308105
#Small Method LC2: 0.000134944915771
#Small Method Pandas: 0.0712950229645
#Large Method LC: 0.0321750640869
#Large Method LC2: 0.0206089019775
#Large Method Pandas: 5.81405615807

假设我有一个字典D,它的元素在下面。要进行排序,只需使用关键参数in ordered来传递自定义函数,如下所示

1
2
3
4
5
6
7
8
D = {'eggs': 3, 'ham': 1, 'spam': 2}

def get_count(tuple):
    return tuple[1]

sorted(D.items(), key = get_count, reverse=True)
or
sorted(D.items(), key = lambda x: x[1], reverse=True)  avoiding get_count function call

https://wiki.python.org/moin/HowTo/Sorting/#Key_Functions


下面是我对一个有关按多列排序的问题的回答。它也适用于列数只有1的简并情况。


如果不需要dictionaries的原始list,可以使用自定义键函数用sort()方法就地修改它。

主要功能:

1
2
3
4
def get_name(d):
   """ Return the value of a key in a dictionary."""

    return d["name"]

待排序的list:

1
data_one = [{'name': 'Homer', 'age': 39}, {'name': 'Bart', 'age': 10}]

就地排序:

1
data_one.sort(key=get_name)

如果需要原始的list,调用sorted()函数,传递给它list和key函数,然后将返回的排序后的list赋给一个新变量:

1
2
data_two = [{'name': 'Homer', 'age': 39}, {'name': 'Bart', 'age': 10}]
new_data = sorted(data_two, key=get_name)

打印data_onenew_data

1
2
3
4
>>> print(data_one)
[{'name': 'Bart', 'age': 10}, {'name': 'Homer', 'age': 39}]
>>> print(new_data)
[{'name': 'Bart', 'age': 10}, {'name': 'Homer', 'age': 39}]

如果要考虑性能,可以使用itemgetter。itemgetter通常比lambda运行得快一些。

1
2
from operator import itemgetter
result = sorted(data, key=itemgetter('age'))  # this will sort list by property order 'age'.

您可以使用以下代码

1
sorted_dct = sorted(dct_name.items(), key = lambda x : x[1])

推荐阅读

    linuxps命令排序?

    linuxps命令排序?,系统,状态,情况,基础,软件,进程,工具,命令,实时,发行,linux

    linux常用命令字典?

    linux常用命令字典?,状态,代码,环境,信息,项目,发行,标准,电脑,基础,文件,lin

    文件夹排序linux命令?

    文件夹排序linux命令?,系统,数字,信息,工作,时间,命令,管理,设备,单位,工具,

    linuxls命令排序?

    linuxls命令排序?,工作,系统,信息,数据,命令,目录,标准,基础,管理,时间,Linux

    linux磁盘列表命令?

    linux磁盘列表命令?,情况,管理,系统,单位,信息,数据,命令,磁盘,服务,时间,lin

    linux排序数字命令?

    linux排序数字命令?,标准,数字,单位,情况,系统,信息,命令,文件,顺序,参数,lin

    linuxll排序命令?

    linuxll排序命令?,系统,信息,地址,标准,工作,命令,时间,数据,文件,目录,Linux

    linux命令筛选列表?

    linux命令筛选列表?,工具,状态,位置,工作,预期,命令,名称,标准,数据,系统,在L

    linux的长列表命令?

    linux的长列表命令?,工作,系统,信息,命令,数据,目录,电脑,软件,时间,设备,Lin

    linux创建数组命令?

    linux创建数组命令?,地址,工作,系统,信息,命令,代码,目录,情况,标准,文件,Lin

    linux命令按大小排序?

    linux命令按大小排序?,数字,地址,时间,工作,标准,系统,命令,信息,单位,软件,l

    linux目录列表命令?

    linux目录列表命令?,系统,信息,标准,工作,命令,地址,时间,数据,名称,目录,lin

    linux计数排序命令?

    linux计数排序命令?,标准,命令,情况,工作,文件,系统,数字,管理,目录,内容,Lin

    linux下排序命令怎么?

    linux下排序命令怎么?,本行,命令,代码,数字,位置,单位,标准,文件,参数,文本,l

    linux按字符排序命令?

    linux按字符排序命令?,标准,命令,时间,情况,文件,数字,基础,状态,系统,功能,i

    linux字典排序命令?

    linux字典排序命令?,工作,系统,标准,信息,命令,时间,数字,单位,状态,软件,Lin