如何按照Python中字典的值对字典列表进行sorting?
我得到了一个字典列表,并希望按字典的值进行sorting。
这个
[{'name':'Homer', 'age':39}, {'name':'Bart', 'age':10}]
按名称sorting,应该成为
[{'name':'Bart', 'age':10}, {'name':'Homer', 'age':39}]
它可能看起来更清洁使用一个键,而不是一个cmp:
newlist = sorted(list_to_be_sorted, key=lambda k: k['name'])
或者像JFSebastian和其他人所build议的那样,
from operator import itemgetter newlist = sorted(list_to_be_sorted, key=itemgetter('name'))
为了完整性(正如在fitzgeraldsteele的评论中指出的),添加reverse=True
来降序sorting
newlist = sorted(l, key=itemgetter('name'), reverse=True)
import operator
按键=“名称”对字典列表进行sorting:
list_of_dicts.sort(key=operator.itemgetter('name'))
按键='年龄'对字典列表进行sorting:
list_of_dicts.sort(key=operator.itemgetter('age'))
如果您想按多个键对列表进行sorting,您可以执行以下操作:
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']))
这是相当黑客的,因为它依赖于将值转换为一个单一的string表示forms进行比较,但它可以按照预期的方式对包括负数的数字进行操作(尽pipe如果您使用的是数字,则需要使用零填充来适当地格式化string)
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
参数更有效率,更整洁。 现在更好的答案是:
my_list = sorted(my_list, key=lambda k: k['name'])
… lambda是IMO,比operator.itemgetter
更容易理解,但是YMMV。
import operator a_list_of_dicts.sort(key=operator.itemgetter('name'))
'key'用于按任意值sorting,'itemgetter'将该值设置为每个项目的'name'属性。
我想你的意思是:
[{'name':'Homer', 'age':39}, {'name':'Bart', 'age':10}]
这将被sorting如下:
sorted(l,cmp=lambda x,y: cmp(x['name'],y['name']))
使用Perl的Schwartzian转换,
py = [{'name':'Homer', 'age':39}, {'name':'Bart', 'age':10}]
做
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变换
在计算机科学中,Schwartzian变换是一种Perl编程习惯用法,用于提高对项目列表进行sorting的效率。 这个习惯用法适用于基于比较的sorting,当sorting实际上是基于元素的某个属性(关键)的sorting时,其中计算该属性是应该执行最less次数的密集操作。 Schwartzian变换值得注意的是它不使用命名的临时数组。
你必须实现你自己的比较函数,它将用名字键的值来比较字典。 请参阅从PythonInfo Wiki中sortingMini-HOW TO
您可以使用自定义比较函数,也可以传入计算自定义sorting键的函数。 这通常更有效,因为密钥只是每个项目计算一次,而比较函数将被调用更多次。
你可以这样做:
def mykey(adict): return adict['name'] x = [{'name': 'Homer', 'age': 39}, {'name': 'Bart', 'age':10}] sorted(x, key=mykey)
但是标准库包含一个获取任意对象项的通用例程: itemgetter
。 所以试试这个:
from operator import itemgetter x = [{'name': 'Homer', 'age': 39}, {'name': 'Bart', 'age':10}] sorted(x, key=itemgetter('name'))
我尝试了这样的事情:
my_list.sort(key=lambda x: x['name'])
它也适用于整数。
这里是另一个通用的解决scheme – 它通过键和值对字典的元素进行sorting。 它的优点 – 不需要指定键,如果某些字典中某些键丢失,它仍然可以工作。
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)
让我们说一下带有下面元素的字典D. sorting只是在sorting中使用键parameter passing自定义函数如下
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
使用pandas软件包是另一种方法,虽然大规模运行时比其他人提出的更传统的方法慢得多:
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 +)字典列表的基准值:
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
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'])
有时我们需要使用lower()
作为例子
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}]
这是我对多列sorting相关问题的回答 。 它也适用于列数只有一个的退化情况。