Belirli bir dizindeki öğeye göre liste / liste / grup dizisi nasıl sıralanır?


658

Ben liste veya tuples bir listede bazı veriler var, böyle:

data = [[1,2,3], [4,5,6], [7,8,9]]
data = [(1,2,3), (4,5,6), (7,8,9)]

Ve altkümedeki 2. öğeye göre sıralamak istiyorum. 2,5,8 göre sıralama Anlam 2dan (1,2,3), 5dan (4,5,6). Bunu yapmanın ortak yolu nedir? Listede tuples veya listeler saklamalı mıyım?


51
"Listede tuples veya listeler saklamalı mıyım?" Eğer yoksa ihtiyaç yerde sublists değiştirmek için, onları Tuples olun.
Matthew Flaschen

Yanıtlar:


1115
sorted_by_second = sorted(data, key=lambda tup: tup[1])

veya:

data.sort(key=lambda tup: tup[1])  # sorts in place

10
Daha büyükten küçüğe nasıl sıralayacağına dair bir fikrin var mı?
billwild

63
@billwild: yardım (sıralanmış). = Gerçek ters.
Stephen

34
@ İtemgetter kullanarak Stephen daha hızlı ve daha basit: key=itemgetter(1)ve dosyanın başında:from operator import itemgetter
Joschua

3
İkinci örnekte sortolduğu gibi, burada parametre Listolarak bir lambda işlevi alan Python'un bir nesne yöntemi key. Sen isim olarak verebilir tupya tya da benzeri her ne ve çalışma hala olacak. tupburada listenin grubunun dizinini belirtir, bu nedenle 1sıralama, orijinal listeden ( 2, 5, 8) başlıkların ikinci değerleri tarafından gerçekleştirileceği anlamına gelir .
Nörotransmitter

1
"İtemgetter'ı kullanmak daha hızlı ve daha basit" iddiası bulunmadığı konusunda oldukça şüpheliydim. Öznel olarak sezgisel lambdayaklaşımı , sezgisel olmayan itemgettersınıftan daha basit olarak görsem de itemgetter , gerçekten daha hızlı görünüyor . Bunun neden olduğunu merak ediyorum. Benim lambdakuşkum şudur ki , tüm yerel değişkenleri bir kapanış bağlamında yakalamanın gizli maliyetine katlanırken, bir itemgetterörnek bunu yapmaz. tl; dr: Her zaman kullanın itemgetter, çünkü hız kazanır.
Cecil Curry

236
from operator import itemgetter
data.sort(key=itemgetter(1))

37
Bu kabul edilen cevap olmalı. Ayrıca bkz Charlie 'nin yayınlanan zamanlamalarını göstererek itemgettersıralamak için sınıf 126% daha hızlı ortalama eşdeğer daha lambdafonksiyonu.
Cecil Curry

9
Ayrıca, hiyerarşik olarak birden çok data.sort(key=itemgetter(3,1))
dizine

57

Eğer diziyi yüksekten düşüğe doğru sıralamak istiyorsanız, sadece yukarıdaki açıklamalardan başka bir yol sadece bu satır eklemek için Stephen'ın cevabına eklemek istiyorum:

reverse = True

ve sonuç aşağıdaki gibi olacaktır:

data.sort(key=lambda tup: tup[1], reverse=True)

48

Birden çok kritere göre, örneğin bir demet içindeki ikinci ve üçüncü öğelere göre sıralama için,

data = [(1,2,3),(1,2,1),(1,1,4)]

ve böylece önceliği tanımlayan bir demet döndüren bir lambda tanımlayın, örneğin

sorted(data, key=lambda tup: (tup[1],tup[2]) )
[(1, 1, 4), (1, 2, 1), (1, 2, 3)]

28

Stephen'ın cevabı kullanacağım. Tamlık için, liste anlayışına sahip DSU (decorate-sort-undecorate) modeli:

decorated = [(tup[1], tup) for tup in data]
decorated.sort()
undecorated = [tup for second, tup in decorated]

Veya daha tersine:

[b for a,b in sorted((tup[1], tup) for tup in data)]

Python Sorting HowTo'da belirtildiği gibi , bu, anahtar işlevlerin kullanıma sunulduğu Python 2.4'ten beri gereksizdi.


2
Peki bu cevap Python 2.3- için faydalıdır? Daha güncel Python sürümlerinde, etrafını biraz ayrıntılandırabileceğiniz geçerli kullanımlar var mı? Değilse, hiçbir rahatsızlık ... sadece geçiyordu, bunu gördüm ve eski noggin sadece bir çırpıda çalkaladı. Her neyse, şerefe ve Python'un önceki günlerine bu yürüyüş için teşekkürler.
mechanical_meat

19

Dizilerini bir listesini sıralamak için (<word>, <count>)için, countazalan sırayla ve wordalfabetik sıraya göre:

data = [
('betty', 1),
('bought', 1),
('a', 1),
('bit', 1),
('of', 1),
('butter', 2),
('but', 1),
('the', 1),
('was', 1),
('bitter', 1)]

Bu yöntemi kullanıyorum:

sorted(data, key=lambda tup:(-tup[1], tup[0]))

ve sonuç veriyor:

[('butter', 2),
('a', 1),
('betty', 1),
('bit', 1),
('bitter', 1),
('bought', 1),
('but', 1),
('of', 1),
('the', 1),
('was', 1)]

1
tup [1] bir dize ise ne olur?
eric

12

Lambda olmadan:

def sec_elem(s):
    return s[1]

sorted(data, key=sec_elem)

9

itemgetter()biraz daha hızlı lambda tup: tup[1], ancak artış nispeten mütevazı (yaklaşık yüzde 10 ila 25).

(IPython oturumu)

>>> from operator import itemgetter
>>> from numpy.random import randint
>>> values = randint(0, 9, 30000).reshape((10000,3))
>>> tpls = [tuple(values[i,:]) for i in range(len(values))]

>>> tpls[:5]    # display sample from list
[(1, 0, 0), 
 (8, 5, 5), 
 (5, 4, 0), 
 (5, 7, 7), 
 (4, 2, 1)]

>>> sorted(tpls[:5], key=itemgetter(1))    # example sort
[(1, 0, 0), 
 (4, 2, 1), 
 (5, 4, 0), 
 (8, 5, 5), 
 (5, 7, 7)]

>>> %timeit sorted(tpls, key=itemgetter(1))
100 loops, best of 3: 4.89 ms per loop

>>> %timeit sorted(tpls, key=lambda tup: tup[1])
100 loops, best of 3: 6.39 ms per loop

>>> %timeit sorted(tpls, key=(itemgetter(1,0)))
100 loops, best of 3: 16.1 ms per loop

>>> %timeit sorted(tpls, key=lambda tup: (tup[1], tup[0]))
100 loops, best of 3: 17.1 ms per loop

Burada birden çok sütun için değişen ters argümanlar için itemgetter sıralama çözümüne bakın, ardından sıralamanızı art arda birden fazla adımda düzenlemeniz gerekir: stackoverflow.com/questions/14466068/…
Lorenz

6

@Stephen'in cevabı noktaya geldi! İşte daha iyi görselleştirme için bir örnek,

Ready Player One hayranları için seslenin! =)

>>> gunters = [('2044-04-05', 'parzival'), ('2044-04-07', 'aech'), ('2044-04-06', 'art3mis')]
>>> gunters.sort(key=lambda tup: tup[0])
>>> print gunters
[('2044-04-05', 'parzival'), ('2044-04-06', 'art3mis'), ('2044-04-07', 'aech')]

keycompareToJava için koleksiyon yöntemi gibi karşılaştırma için öğeleri dönüştürmek için çağrılacak bir işlevdir .

Anahtara iletilen parametre, çağrılabilir bir şey olmalıdır. Burada, kullanımı lambdaanonim bir işlev oluşturur (bu çağrılabilir).
Lambda sözdizimi, lambda kelimesinin ardından yinelenebilir bir ad ve ardından tek bir kod bloğudur.

Aşağıdaki örnekte, belirli bir olayın ve oyuncu adının bilgi zamanını tutan bir grup listesi sıralıyoruz.

Bu listeyi olayın meydana gelme zamanına göre sıralıyoruz - bu da bir grubun 0. elemanıdır.

Not - s.sort([cmp[, key[, reverse]]]) s öğelerini yerinde sıralar


-5

Bir demet sıralamak oldukça basittir:

tuple(sorted(t))
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.