Saya memiliki daftar kamus dan ingin setiap item yang akan diurutkan berdasarkan tertentu nilai properti.
Mempertimbangkan array di bawah ini,
[{'name':'Homer', 'age':39}, {'name':'Bart', 'age':10}]
Bila diurutkan berdasarkan nama
, harus menjadi
[{'name':'Bart', 'age':10}, {'name':'Homer', 'age':39}]
Ini mungkin terlihat bersih menggunakan kunci bukan cmp:
newlist = sorted(list_to_be_sorted, key=lambda k: k['name'])
atau seperti J. F. Sebastian dan lain-lain yang disarankan,
from operator import itemgetter
newlist = sorted(list_to_be_sorted, key=itemgetter('name'))
Untuk kelengkapan (seperti yang ditunjukkan di komentar oleh fitzgeraldsteele), tambahkan reverse=True
untuk sort descending
newlist = sorted(l, key=itemgetter('name'), reverse=True)
import operator
Untuk mengurutkan daftar kamus dengan kunci='nama':
list_of_dicts.sort(key=operator.itemgetter('name'))
Untuk mengurutkan daftar kamus dengan kunci='usia':
list_of_dicts.sort(key=operator.itemgetter('age'))
my_list = [{'name':'Homer', 'age':39}, {'name':'Bart', 'age':10}]
my_list.sort(lambda x,y : cmp(x['name'], y['name']))
my_list
sekarang akan menjadi apa yang anda inginkan.
(3 tahun kemudian) Diedit untuk menambahkan:
Baru kunci
argumen lebih efisien dan lebih rapi. Jawaban yang lebih baik sekarang terlihat seperti:
my_list = sorted(my_list, key=lambda k: k['name'])
...lambda adalah, IMO, lebih mudah untuk memahami dari operator.itemgetter
, tapi YMMV.
Jika anda ingin mengurutkan daftar berdasarkan beberapa tombol anda dapat melakukan hal-hal berikut:
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']))
Hal ini agak hackish, karena hal itu bergantung pada konversi nilai ke dalam satu string representasi sebagai perbandingan, tetapi bekerja seperti yang diharapkan untuk angka termasuk yang negatif (meskipun anda akan perlu untuk memformat string secara tepat dengan nol bantalan jika anda menggunakan angka)
Anda bisa menggunakan custom perbandingan fungsi, atau anda bisa lulus dalam suatu fungsi yang menghitung semacam kustom kunci. Yang's biasanya lebih efisien sebagai kunci dihitung hanya sekali per item, sedangkan perbandingan fungsi akan dipanggil berkali-kali lebih banyak.
Anda bisa melakukannya dengan cara ini:
def mykey(adict): return adict['name']
x = [{'name': 'Homer', 'age': 39}, {'name': 'Bart', 'age':10}]
sorted(x, key=mykey)
Tapi standar perpustakaan berisi generik rutin untuk mendapatkan barang-barang dari objek sewenang-wenang: itemgetter
. Jadi coba ini sebagai gantinya:
from operator import itemgetter
x = [{'name': 'Homer', 'age': 39}, {'name': 'Bart', 'age':10}]
sorted(x, key=itemgetter('name'))
Menggunakan Schwartzian mengubah dari Perl,
py = [{'name':'Homer', 'age':39}, {'name':'Bart', 'age':10}]
lakukan
sort_on = "name"
decorated = [(dict_[sort_on], dict_) for dict_ in py]
decorated.sort()
result = [dict_ for (key, dict_) in decorated]
memberikan
>>> result
[{'age': 10, 'name': 'Bart'}, {'age': 39, 'name': 'Homer'}]
Lebih lanjut di Perl Schwartzian transform
Dalam ilmu komputer, Schwartzian transform adalah pemrograman Perl idiom yang digunakan untuk meningkatkan efisiensi pemilahan daftar item. Ini ungkapan ini tepat untuk comparison-based sorting saat pemesanan benar-benar berdasarkan urutan dari properti tertentu (kunci) dari unsur-unsur, di mana komputasi properti yang intensif operasi yang harus dilakukan minimal jumlah kali. Yang Schwartzian Transform adalah penting dalam bahwa hal itu tidak menggunakan nama sementara array.
kadang-kadang kita perlu menggunakan yang lebih rendah()
misalnya
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}]
Berikut ini adalah alternatif solusi umum - macam elemen dari dict dengan kunci dan nilai-nilai. Keuntungan dari itu - tidak perlu untuk menentukan kunci, dan itu akan tetap bekerja jika beberapa kunci yang hilang dalam beberapa kamus.
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)
Menggunakan panda paket metode lain, meskipun itu's runtime pada skala besar adalah jauh lebih lambat dibandingkan dengan metode yang lebih tradisional yang diusulkan oleh orang lain:
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()
Berikut ini adalah beberapa acuan nilai-nilai untuk sebuah daftar kecil dan besar (100k+) daftar 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
Let's mengatakan saya memiliki kamus D
dengan unsur-unsur di bawah ini. Untuk mengurutkan hanya menggunakan kunci argumen yang diurutkan untuk lulus kustom fungsi sebagai berikut :
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
Check ini keluar.
Jika anda tidak perlu asli daftar
dari kamus
, anda bisa memodifikasinya di-tempat dengan sort()
menggunakan metode kustom fungsi kunci.
Fungsi utama:
def get_name(d):
""" Return the value of a key in a dictionary. """
return d["name"]
Daftar
yang akan diurutkan:
data_one = [{'name': 'Homer', 'age': 39}, {'name': 'Bart', 'age': 10}]
Penyortiran ini di tempat:
data_one.sort(key=get_name)
Jika anda membutuhkan asli daftar
, menelepon diurutkan()
fungsi lewat itu daftar
dan tombol fungsi, kemudian menetapkan kembali diurutkan daftar
untuk variabel baru:
data_two = [{'name': 'Homer', 'age': 39}, {'name': 'Bart', 'age': 10}]
new_data = sorted(data_two, key=get_name)
Percetakan data_one
dan new_data
.
>>> print(data_one)
[{'name': 'Bart', 'age': 10}, {'name': 'Homer', 'age': 39}]
>>> print(new_data)
[{'name': 'Bart', 'age': 10}, {'name': 'Homer', 'age': 39}]
Saya telah menjadi penggemar besar dari filter w/ lambda namun itu bukan pilihan terbaik jika anda mempertimbangkan kompleksitas waktu
Pilihan pertama
sorted_list = sorted(list_to_sort, key= lambda x: x['name'])
# returns list of values
Pilihan kedua
list_to_sort.sort(key=operator.itemgetter('name'))
#edits the list, does not return a new list
Cepat perbandingan exec kali
# 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 loop, terbaik dari 3: 0.736 usec per loop
# 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 loop, terbaik dari 3: 0.438 usec per loop