Yanıtlar:
Bir cmp yerine bir anahtar kullanarak daha temiz görünebilir:
newlist = sorted(list_to_be_sorted, key=lambda k: k['name'])
veya JFSebastian ve diğerlerinin önerdiği gibi,
from operator import itemgetter
newlist = sorted(list_to_be_sorted, key=itemgetter('name'))
Tamlık için (fitzgeraldsteele tarafından yapılan yorumlarda belirtildiği gibi), reverse=True
azalan sıralamaya ekleyin
newlist = sorted(l, key=itemgetter('name'), reverse=True)
itemgetter(i)
nerede olduğunu kullanırsanız, bir tuples listesi için de geçerlidir i
.
itemgetter
birden fazla argümanı kabul eder: itemgetter(1,2,3)
bir demet gibi dönen bir işlevdir obj[1], obj[2], obj[3]
, bu yüzden karmaşık türler yapmak için kullanabilirsiniz.
import operator
Sözlük listesini key = 'name' ile sıralamak için:
list_of_dicts.sort(key=operator.itemgetter('name'))
Sözlük listesini key = 'age' ile sıralamak için:
list_of_dicts.sort(key=operator.itemgetter('age'))
key=lambda k: (k['name'], k['age'])
. (veya key=itemgetter('name', 'age')
). tuple'lar cmp
sırayla her elemanı karşılaştırır. çok kanlı.
key
argüman list.sort()
açıklanmamıştır. Nerede bulacağına dair bir fikrin var mı?
list
.
my_list = [{'name':'Homer', 'age':39}, {'name':'Bart', 'age':10}]
my_list.sort(lambda x,y : cmp(x['name'], y['name']))
my_list
şimdi istediğin şey olacak.
(3 yıl sonra) Eklemek için düzenlendi:
Yeni key
argüman daha verimli ve daha titiz. Şimdi daha iyi bir cevap şuna benziyor:
my_list = sorted(my_list, key=lambda k: k['name'])
... lambda, IMO, anlaşılması daha kolay operator.itemgetter
, ama YMMV.
Listeyi birden çok tuşa göre sıralamak istiyorsanız aşağıdakileri yapabilirsiniz:
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']))
Değerleri karşılaştırma için tek bir dize temsiline dönüştürmeye dayalı olduğu için oldukça hacklidir, ancak negatif olanlar da dahil olmak üzere sayılar için beklendiği gibi çalışır (sayıları kullanıyorsanız dizenizi sıfır dolguyla uygun şekilde biçimlendirmeniz gerekir)
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'])
Sanırım demek istediniz:
[{'name':'Homer', 'age':39}, {'name':'Bart', 'age':10}]
Bu şu şekilde sıralanır:
sorted(l,cmp=lambda x,y: cmp(x['name'],y['name']))
Özel bir karşılaştırma işlevi kullanabilir veya özel bir sıralama anahtarı hesaplayan bir işlevi iletebilirsiniz. Anahtar genellikle öğe başına sadece bir kez hesaplandığından, genellikle daha etkilidir; karşılaştırma fonksiyonu ise birçok kez çağrılır.
Bunu şu şekilde yapabilirsiniz:
def mykey(adict): return adict['name']
x = [{'name': 'Homer', 'age': 39}, {'name': 'Bart', 'age':10}]
sorted(x, key=mykey)
Ama standart kütüphane rasgele nesne öğelerini almak için genel bir rutin içerir: itemgetter
. Bunun yerine şunu deneyin:
from operator import itemgetter
x = [{'name': 'Homer', 'age': 39}, {'name': 'Bart', 'age':10}]
sorted(x, key=itemgetter('name'))
Perl'den Schwartz dönüşümünü kullanarak,
py = [{'name':'Homer', 'age':39}, {'name':'Bart', 'age':10}]
yapmak
sort_on = "name"
decorated = [(dict_[sort_on], dict_) for dict_ in py]
decorated.sort()
result = [dict_ for (key, dict_) in decorated]
verir
>>> result
[{'age': 10, 'name': 'Bart'}, {'age': 39, 'name': 'Homer'}]
Perl Schwartz dönüşüm hakkında daha fazla bilgi
Bilgisayar biliminde Schwartz dönüşüm, bir öğe listesini sıralama etkinliğini artırmak için kullanılan bir Perl programlama deyimidir. Bu deyim, sipariş aslında öğelerin belirli bir özelliğinin (anahtarının) sırasına dayandığı zaman karşılaştırma tabanlı sıralama için uygundur, burada bu özelliğin hesaplanması en az sayıda yapılması gereken yoğun bir işlemdir. Schwartz Dönüşümü, adlandırılmış geçici diziler kullanmaması nedeniyle dikkat çekicidir.
key=
için .sort
, 2004 yılı olduğunu, bu C, sıralama kodundaki Schwartzian dönüşümü yoktur 2.4 beri; bu nedenle bu yöntem sadece Pythons 2.0-2.3 için yararlıdır. hepsi 12 yaşından büyük.
Sözlükleri ad anahtarlarının değerleriyle karşılaştıracak kendi karşılaştırma işlevinizi uygulamanız gerekir. Bkz. Mini-NASIL PythonInfo Wiki'den Sıralama
bazen biz kullanmak gerekir lower()
örneğin
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}]
İşte alternatif genel çözüm - dikte unsurlarını anahtarlara ve değerlere göre sıralar. Avantajı - anahtarları belirtmeye gerek yoktur ve bazı sözlüklerde bazı anahtarlar eksikse yine de çalışır.
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)
Panda paketini kullanmak başka bir yöntemdir, ancak büyük ölçekli çalışma zamanı, başkaları tarafından önerilen daha geleneksel yöntemlerden çok daha yavaştır:
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()
Küçük bir liste ve büyük (100k +) dikte listesi için bazı karşılaştırma değerleri şunlardır:
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
Orijinal gerekmiyorsa list
ait dictionaries
, sizinle yerinde değişiklik olabilir sort()
özel bir anahtar işlevi kullanılarak yöntemle.
Anahtar işlevi:
def get_name(d):
""" Return the value of a key in a dictionary. """
return d["name"]
list
Sıralanmasını:
data_one = [{'name': 'Homer', 'age': 39}, {'name': 'Bart', 'age': 10}]
Yerinde sıralama:
data_one.sort(key=get_name)
Orijinaline ihtiyacınız varsa list
, sorted()
onu geçen işlevi list
ve anahtar işlevini çağırın , ardından döndürülen diziyi list
yeni bir değişkene atayın :
data_two = [{'name': 'Homer', 'age': 39}, {'name': 'Bart', 'age': 10}]
new_data = sorted(data_two, key=get_name)
Baskı data_one
ve new_data
.
>>> print(data_one)
[{'name': 'Bart', 'age': 10}, {'name': 'Homer', 'age': 39}]
>>> print(new_data)
[{'name': 'Bart', 'age': 10}, {'name': 'Homer', 'age': 39}]
Diyelim ki D
aşağıdaki öğeleri içeren bir sözlüğüm var. Sıralamak için özel işlevi aşağıdaki gibi geçirmek üzere sıralanmış anahtar tuşunu kullanın:
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
Kontrol bu out.
Lambda filtre w / büyük bir hayranı olmuştur ancak zaman karmaşıklığı göz önüne alındığında en iyi seçenek değil
İlk seçenek
sorted_list = sorted(list_to_sort, key= lambda x: x['name'])
# returns list of values
İkinci seçenek
list_to_sort.sort(key=operator.itemgetter('name'))
#edits the list, does not return a new list
Yürütme sürelerinin hızlı karşılaştırması
# 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 döngü, döngü başına en iyi 3: 0,736 usec
# 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 döngü, döngü başına en iyi 3: 0,438 usec
Performans bir sorun olacaksa, ben kullanırım operator.itemgetter
yerine lambda
daha hızlı el yapımı fonksiyonlarından daha gerçekleştirmek yerleşik işlevler gibi. itemgetter
Fonksiyon göre yaklaşık% 20 daha hızlı gerçekleştirmek gibi görünüyor lambda
benim testlere dayanmaktadır.
Gönderen https://wiki.python.org/moin/PythonSpeed :
Benzer şekilde, yerleşik işlevler el yapımı eşdeğerlerden daha hızlı çalışır. Örneğin, harita (operatör.ekle, v1, v2) haritadan daha hızlıdır (lambda x, y: x + y, v1, v2).
İşte lambda
vs kullanarak sıralama hızı karşılaştırması 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 same sort order
sorted(l, key=lambda x: x['name']) == sorted(l, key=operator.itemgetter('name'))
True
Her iki teknik de listeyi aynı sırada sıralar (kod bloğundaki son ifadenin çalıştırılmasıyla doğrulanır), ancak biri biraz daha hızlıdır.
[{'name':'Bart', 'age':10, 'note':3},{'name':'Homer','age':10,'note':2},{'name':'Vasile','age':20,'note':3}]
Ve kullanmak için:from operator import itemgetter newlist = sorted(old_list, key=itemgetter(-'note','name')
EDIT: Tested, ve çalışıyor ama nasıl DESC ve ASC adını nasıl yapacağımı bilmiyorum.