Câu hỏi Làm cách nào để sắp xếp danh sách từ điển theo giá trị của từ điển bằng Python?


Tôi có danh sách từ điển và muốn được sắp xếp theo giá trị của từ điển đó.

Điều này

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

được sắp xếp theo tên, nên trở thành

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

1344
2017-09-16 14:39


gốc




Các câu trả lời:


Nó có thể trông sạch hơn bằng cách sử dụng một phím thay vì một cmp:

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

hoặc như J.F.Sebastian và những người khác đã đề nghị,

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

Để hoàn thành (như được chỉ ra trong các bình luận của fitzgeraldsteele), thêm reverse=True sắp xếp giảm dần

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

1822
2017-09-16 15:18



Sử dụng khóa không chỉ sạch hơn mà còn hiệu quả hơn nữa. - jfs
lambda k: k['name'] có thể được thay thế bởi operator.itemgetter ('name'). - jfs
Những gì bạn sẽ thay đổi để làm cho nó sắp xếp giảm dần? - NealWalters
Để sắp xếp giảm dần: newlist = sắp xếp (l, key = itemgetter ('name'), reverse = True) - fitzgeraldsteele
itemgetter chấp nhận nhiều hơn một đối số: itemgetter(1,2,3) là một hàm trả về một tuple như obj[1], obj[2], obj[3], vì vậy bạn có thể sử dụng nó để làm các loại phức tạp. - Bakuriu


import operator

Để sắp xếp danh sách từ điển theo key = 'name':

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

Để sắp xếp danh sách từ điển theo key = 'age':

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

109
2017-09-16 14:39



Dù sao để kết hợp tên và tuổi? (giống như trong SQL ORDER BY tên, tuổi?) - monojohnny
lợi thế của itemgetter trên lambda là gì? - njzk2
@monojohnny: vâng, chỉ cần có chìa khóa trả về một tuple, key=lambda k: (k['name'], k['age']). (hoặc là key=itemgetter('name', 'age')). tuple's cmp sẽ so sánh từng phần tử lần lượt. nó rực rỡ máu. - Claudiu
Trong tài liệu (docs.python.org/2/tutorial/datastructures.html) tùy chọn key đối số cho list.sort() không được mô tả. Bất kỳ ý tưởng nơi để tìm thấy điều đó? - TTT
@TTT: Xem tài liệu thư viện cho list và những người bạn. - Kevin


Nếu bạn muốn sắp xếp danh sách theo nhiều khóa, bạn có thể thực hiện các thao tác sau:

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']))

Nó khá là đáng sợ, vì nó dựa vào việc chuyển đổi các giá trị thành một biểu diễn chuỗi để so sánh, nhưng nó hoạt động như mong đợi cho các số bao gồm cả số âm (mặc dù bạn sẽ cần phải định dạng chuỗi của bạn một cách thích hợp với paddings zero nếu bạn đang sử dụng số)


39
2017-09-16 14:43



được sắp xếp bằng cách sử dụng timsort ổn định, bạn có thể gọi được sắp xếp nhiều lần để có một sắp xếp trên một số tiêu chí - njzk2
Nhận xét của njzk2 không rõ ràng với tôi vì vậy tôi đã tìm thấy những điều sau đây. Bạn có thể chỉ cần sắp xếp hai lần như njzk2 gợi ý, hoặc chuyển nhiều đối số tới operator.itemgetter trong câu trả lời trên cùng. Liên kết: stackoverflow.com/questions/5212870/… - Permafacture
Không cần phải chuyển đổi thành chuỗi. Chỉ cần trả lại một tuple làm khóa. - Winston Ewert
Sắp xếp nhiều lần là giải pháp chung chung dễ nhất mà không cần hack: stackoverflow.com/a/29849371/1805397 - wouter bolsterlee


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

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

my_list bây giờ sẽ là những gì bạn muốn.

(3 năm sau) Đã chỉnh sửa để thêm:

Cái mới key đối số là hiệu quả hơn và neater. Một câu trả lời tốt hơn bây giờ trông giống như:

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

... lambda là, IMO, dễ hiểu hơn operator.itemgetter, nhưng YMMV.


27
2017-09-16 14:36





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

'khóa' được sử dụng để sắp xếp theo giá trị tùy ý và các bộ 'itemgetter' có giá trị cho thuộc tính 'tên' của mỗi mục.


20
2017-09-16 14:52





Tôi đoán bạn đã có nghĩa là:

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

Điều này sẽ được sắp xếp như thế này:

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

14
2017-09-16 14:31





Bạn có thể sử dụng hàm so sánh tùy chỉnh hoặc bạn có thể chuyển vào hàm tính toán khóa sắp xếp tùy chỉnh. Điều đó thường hiệu quả hơn vì khóa chỉ được tính một lần cho mỗi mục, trong khi hàm so sánh sẽ được gọi nhiều lần hơn.

Bạn có thể làm theo cách này:

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

Nhưng thư viện chuẩn chứa một thói quen chung để nhận các mục của các đối tượng tùy ý: itemgetter. Vì vậy, hãy thử thay vào đó:

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

12





Sử dụng biến đổi của Schwartz từ Perl,

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

làm

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

cho

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

Thông tin thêm về Perl Schwartzian biến đổi

Trong khoa học máy tính, biến đổi Schwartz là một chương trình Perl   thành ngữ được sử dụng để cải thiện hiệu quả phân loại danh sách các mục. Điều này   thành ngữ phù hợp để phân loại dựa trên so sánh khi sắp xếp   thực sự dựa trên thứ tự của một thuộc tính nhất định (khóa) của   các yếu tố, nơi tính toán tài sản đó là một hoạt động chuyên sâu   nên được thực hiện một số lần tối thiểu. Người Schwartz   Biến đổi là đáng chú ý ở chỗ nó không sử dụng các mảng được đặt tên tạm thời.


12



Python đã hỗ trợ key= cho .sort kể từ 2.4, đó là năm 2004, nó biến đổi Schwartz trong mã phân loại, trong C; do đó phương pháp này chỉ hữu ích trên Pythons 2.0-2.3. tất cả đều hơn 12 tuổi. - Antti Haapala


Bạn phải thực hiện chức năng so sánh của riêng bạn mà sẽ so sánh các từ điển theo giá trị của các phím tên. Xem Sắp xếp Mini-HOW tới từ PythonInfo Wiki


11





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']) 

9





Tôi đã thử một cái gì đó như thế này:

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

Nó cũng làm việc cho các số nguyên.


6