it-swarm-vi.tech

Làm cách nào để sắp xếp danh sách từ điển theo giá trị của từ điển?

Tôi có một danh sách từ điển và muốn mỗi mục được sắp xếp theo một giá trị thuộc tính cụ thể.

Hãy xem xét các mảng dưới đây,

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

Khi được sắp xếp theo name, sẽ trở thành

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

Nó có thể trông sạch hơn bằng cách sử dụng một phím thay vì 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 đề xuất,

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

Để hoàn thiện (như được chỉ ra trong các nhận xét của fitzgeraldsteele), hãy thêm reverse=True để sắp xếp giảm dần

newlist = sorted(l, key=itemgetter('name'), reverse=True)
2038
Mario F
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'))
123
vemury

Nếu bạn muốn sắp xếp danh sách theo nhiều khóa, bạn có thể làm như 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à hackish, vì nó dựa vào việc chuyển đổi các giá trị thành một chuỗi đại diện duy nhất để so sánh, nhưng nó hoạt động như mong đợi đối với các số bao gồm cả số âm (mặc dù bạn sẽ cần định dạng chuỗi của mình một cách phù hợp với số 0 nếu bạn đang sử dụng số)

43
Dologan
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:

Đối số key mới hiệu quả và gọn gàng hơn. 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.

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

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

26
efotinis

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']))
18
Bartosz Radaczyński

Sử dụng biến đổi Schwartzian 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êm về Biến đổi Perl Schwartzian

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

17
octoback
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']) 
15
forzagreen

Bạn có thể sử dụng chức năng so sánh tùy chỉnh hoặc bạn có thể chuyển vào một 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 chức năng 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ử điều này thay thế:

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

Bạn phải thực hiện chức năng so sánh của riêng mình để so sánh các từ điển theo các giá trị của các khóa tên. Xem Sắp xếp Mini-CÁCH ĐẾN từ PythonInfo Wiki

14
Matej

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

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

Nó làm việc cho số nguyên là tốt.

10
Sandip Agarwal

đôi khi chúng ta cần sử dụng lower() chẳng hạn

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}]
9
uingtea

Đây là giải pháp chung thay thế - nó sắp xếp các yếu tố của dict theo khóa và giá trị . Ưu điểm của nó - không cần chỉ định khóa và nó vẫn hoạt động nếu một số khóa bị thiếu trong một số từ điển.

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)
9
vvladymyrov

Sử dụng gói gấu trúc là một phương pháp khác, mặc dù thời gian chạy của nó ở quy mô lớn chậm hơn nhiều so với các phương pháp truyền thống được đề xuất bởi những người khác:

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()

Dưới đây là một số giá trị điểm chuẩn cho một danh sách nhỏ và một danh sách lớn (100k +) dicts:

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
8
abby sobh

Hãy nói rằng tôi là một từ điển D với các yếu tố dưới đây. Để sắp xếp chỉ cần sử dụng đối số khóa trong sắp xếp để truyền chức năng tùy chỉnh như dưới đây

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_Fifts

5
Shank_Transformer

Đây là câu trả lời của tôi cho một câu hỏi liên quan về sắp xếp theo nhiều cột . Nó cũng hoạt động cho trường hợp suy biến trong đó số lượng cột chỉ là một.

4
hughdbrown

Nếu bạn không cần list gốc của dictionaries, bạn có thể sửa đổi tại chỗ bằng phương thức sort() bằng cách sử dụng chức năng khóa tùy chỉnh.

Chức năng chính:

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

    return d["name"]

list được sắp xếp:

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

Sắp xếp nó tại chỗ:

data_one.sort(key=get_name)

Nếu bạn cần list ban đầu, hãy gọi hàm sorted() truyền cho nó hàm list và sau đó gán hàm list được trả về cho một biến mới:

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

In data_onenew_data.

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

Bạn có thể sử dụng itemgetter , nếu bạn muốn xem xét hiệu suất. itemgetter thường chạy nhanh hơn lambda .

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

Bạn có thể sử dụng mã sau đây

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