如何按特定键的值对词典列表进行排序?鉴于:

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

按名称排序时,应为:

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

当前回答

import operator

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

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

要按key='age'对词典列表进行排序,请执行以下操作:

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

其他回答

使用来自Perl的Schwartzian变换,

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

do

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

给予

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

有关Perl Schwartzian转换的更多信息:

在计算机科学中,施瓦茨变换是一种Perl编程用于提高项目列表排序效率的习惯用法。这当排序为实际上基于元素,其中计算该属性是一项密集的操作应执行最少次数。施瓦茨学派Transform的显著之处在于它不使用命名的临时数组。

如果不需要字典的原始列表,可以使用自定义键函数使用sort()方法对其进行修改。

关键功能:

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

    return d["name"]

要排序的列表:

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

将其分类到位:

data_one.sort(key=get_name)

如果需要原始列表,请调用sorted()函数,将列表和键函数传递给它,然后将返回的排序列表分配给新变量:

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

正在打印data_one和new_data。

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

我一直是lambda过滤器的忠实粉丝。然而,若考虑到时间复杂性,这并不是最好的选择。

第一个选项

sorted_list = sorted(list_to_sort, key= lambda x: x['name'])
# Returns list of values

第二个选项

list_to_sort.sort(key=operator.itemgetter('name'))
# Edits the list, and does not return a new list

快速比较执行时间

# First option
python3.6 -m timeit -s "list_to_sort = [{'name':'Homer', 'age':39}, {'name':'Bart', 'age':10}, {'name':'Faaa', 'age':57}, {'name':'Errr', 'age':20}]" -s "sorted_l=[]" "sorted_l = sorted(list_to_sort, key=lambda e: e['name'])"

1000000个循环,最好为3个:每个循环0.736µsec

# Second option
python3.6 -m timeit -s "list_to_sort = [{'name':'Homer', 'age':39}, {'name':'Bart', 'age':10}, {'name':'Faaa', 'age':57}, {'name':'Errr', 'age':20}]" -s "sorted_l=[]" -s "import operator" "list_to_sort.sort(key=operator.itemgetter('name'))"

1000000个循环,最好为3个:每个循环0.438µsec

如果性能是一个问题,我会使用operator.itemgetter而不是lambda,因为内置函数比手工制作的函数执行得更快。根据我的测试,itemgetter函数的执行速度似乎比lambda快20%左右。

从…起https://wiki.python.org/moin/PythonSpeed:

同样,内置函数的运行速度也比手工构建的等效函数快。例如,map(operator.add,v1,v2)比map(lambda x,y:x+y,v1,v2)更快。

下面是lambda与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 the same sort order
sorted(l, key=lambda x: x['name']) == sorted(l, key=operator.itemgetter('name'))
True

这两种技术都以相同的顺序对列表进行排序(通过在代码块中执行最终语句来验证),但第一种排序速度稍快。

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

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

my_list现在将是您想要的。

或者更好:

自从Python2.4以来,有一个关键的论点更高效、更整洁:

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

…lambda比operator.itemgetter更容易理解,但您的里程数可能会有所不同。