Refaktoryzowałem stary kod i natknąłem się na to:
alist.sort(cmp_items)
def cmp_items(a, b):
if a.foo > b.foo:
return 1
elif a.foo == b.foo:
return 0
else:
return -1
Kod działa (i napisałem go około 3 lata temu!), Ale nie mogę znaleźć tego udokumentowanego nigdzie w dokumentacji Pythona i wszyscy używają go sorted()
do implementacji niestandardowego sortowania. Czy ktoś może wyjaśnić, dlaczego to działa?
sorted()
isort()
oferują niestandardowe sortowanie w bardzo podobny sposób, modulo różnicę w konwencji wywoływania.key
parametru jest lepsze niż przekazywaniecmp
funkcji. (Ta późniejsza nie jest nawet zaimplementowana w Pythonie 3)foo
, w przeciwnym razie wybuchnie. Lepiej zdefiniować niestandardową__lt__()
metodę dla swojej klasy, tosorted()
ilist.sort()
będzie działać out-of-the-box. (Przy okazji, obiekty nie muszą już definiować__cmp__()
, po prostu__lt__()
. Zobacz toOdpowiedzi:
Jest to udokumentowane tutaj .
źródło
cmp
, dostajęTypeError: 'cmp' is an invalid keyword argument for this function
. Co tu się dzieje?sort
funkcja porównania nie przyjmuje funkcji porównawczej jako argumentu w Pythonie 3, a nie jako coś, co naprawdę chciałbym zrobić.Na marginesie, oto lepsza alternatywa dla zaimplementowania tego samego sortowania:
alist.sort(key=lambda x: x.foo)
Lub alternatywnie:
import operator alist.sort(key=operator.attrgetter('foo'))
Sprawdź jak sortować , jest to bardzo przydatne.
źródło
Tak jak w tym przykładzie. Chcesz posortować tę listę.
[('c', 2), ('b', 2), ('a', 3)]
wynik:
[('a', 3), ('b', 2), ('c', 2)]
powinieneś posortować krotki według drugiej pozycji, a następnie pierwszej:
def letter_cmp(a, b): if a[1] > b[1]: return -1 elif a[1] == b[1]: if a[0] > b[0]: return 1 else: return -1 else: return 1
Następnie przekonwertuj go na kluczową funkcję:
from functools import cmp_to_key letter_cmp_key = cmp_to_key(letter_cmp))
Teraz możesz użyć własnego porządku sortowania:
[('c', 2), ('b', 2), ('a', 3)].sort(key=letter_cmp_key)
źródło
To nie działa w Pythonie 3.
Możesz jednak użyć functools cmp_to_key, aby działały funkcje porównawcze w starym stylu.
from functools import cmp_to_key def cmp_items(a, b): if a.foo > b.foo: return 1 elif a.foo == b.foo: return 0 else: return -1 cmp_items_py3 = cmp_to_key(cmp_items) alist.sort(cmp_items_py3)
źródło
Wiem, że wielu już opublikowało dobre odpowiedzi. Jednak chcę zasugerować jedną przyjemną i łatwą metodę bez importowania żadnej biblioteki.
l = [(2, 3), (3, 4), (2, 4)] l.sort(key = lambda x: (-x[0], -x[1]) ) print(l) l.sort(key = lambda x: (x[0], -x[1]) ) print(l)
Wyjście będzie
[(3, 4), (2, 4), (2, 3)] [(2, 4), (2, 3), (3, 4)]
Dane wyjściowe zostaną posortowane na podstawie kolejności parametrów, które podaliśmy w formacie krotki
źródło
Nawet lepiej:
student_tuples = [ ('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10), ] sorted(student_tuples, key=lambda student: student[2]) # sort by age [('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
Zaczerpnięte z: https://docs.python.org/3/howto/sorting.html
źródło