N'inci elemanlar bir tuple listesinden nasıl çıkarılır?


112

N'inci öğeleri bir tuple listesinden almaya çalışıyorum.

Bende şöyle bir şey var:

elements = [(1,1,1),(2,3,7),(3,5,10)]

Her demetin yalnızca ikinci öğelerini bir listeye çıkarmak istiyorum:

seconds = [1, 3, 5]

Bir fordöngü ile yapılabileceğini biliyorum ama binlerce demetim olduğu için başka bir yol olup olmadığını bilmek istedim.

Yanıtlar:


185
n = 1 # N. . .
[x[n] for x in elements]

34

Bu aynı zamanda çalışır:

zip(*elements)[1]

(Başlıca bunu kendime ispatlamak için gönderiyorum zip...)

Eylemde görün:

>>> help(zip)

Modül yerleşikinde yerleşik zip işlevi hakkında yardım :

zip (...)

zip (sıra1 [, sıra2 [...]]) -> [(sıra1 [0], sıra2 [0] ...), (...)]

Her demet, bağımsız değişken dizilerinin her birinden i'inci öğeyi içerdiği bir demet listesi döndürür. Döndürülen listenin uzunluğu, en kısa bağımsız değişken dizisinin uzunluğuna kısaltılır.

>>> elements = [(1,1,1),(2,3,7),(3,5,10)]
>>> zip(*elements)
[(1, 2, 3), (1, 3, 5), (1, 7, 10)]
>>> zip(*elements)[1]
(1, 3, 5)
>>>

Bugün öğrendiğim güzel şey: *listBir işlev için bir parametre listesi oluşturmak için bağımsız değişkenlerde kullanın ...

Not : Python3'te zipbir yineleyici döndürür, bu nedenle bunun yerine list(zip(*elements))bir tuple listesi döndürmek için kullanın .


2
ve **dictanahtar kelime argümanları oluşturmak için kullanın : def test(foo=3, bar=3): return foo*baro zamand = {'bar': 9, 'foo'=12}; print test(**d)
Wayne Werner

@Wayne Werner: Evet. Bu malzeme hepsi sadece pasif bilgi (daha çok ben kullanmayın) - ama bilesin 's iyi şimdi ve sonra hatırlatılmasını nereye / ne aramak için ...
Daren Thomas

1
Gerçek hikaye - Yeterince sık kullandığım herhangi bir şeyde (Python, vim), unuttuğum temiz / havalı özellikleri o kadar sık kullanmadığım için hatırlatıcılara ihtiyacım olduğunu anlıyorum .
Wayne Werner

* liste sözdizimi oldukça kullanışlıdır. bunun resmi python belgelerinde nerede açıklandığı hakkında bir fikriniz var mı?
user1748155

Bunu sadece öğreticide buldum: docs.python.org/2/tutorial/…
Daren Thomas

30

Bir FOR ile yapılabileceğini biliyorum ama başka bir yol olup olmadığını öğrenmek istedim

Başka bir yol var. Bunu harita ve öğe hedefleyici ile de yapabilirsiniz :

>>> from operator import itemgetter
>>> map(itemgetter(1), elements)

Bu yine de dahili olarak bir döngü gerçekleştirir ve listeyi anlamadan biraz daha yavaştır:

setup = 'elements = [(1,1,1) for _ in range(100000)];from operator import itemgetter'
method1 = '[x[1] for x in elements]'
method2 = 'map(itemgetter(1), elements)'

import timeit
t = timeit.Timer(method1, setup)
print('Method 1: ' + str(t.timeit(100)))
t = timeit.Timer(method2, setup)
print('Method 2: ' + str(t.timeit(100)))

Sonuçlar:

Yöntem 1: 1.25699996948
Yöntem 2: 1.46600008011

Bir listeyi yinelemeniz gerekiyorsa, a kullanmak foriyidir.


2
Küçük bir ekleme: python-3.x'te kıyaslama, haritanın yalnızca bir milisaniyenin bir kısmını aldığını gösterecektir. Bunun nedeni, bir yineleyici döndürecek olmasıdır. method2 = 'list (map (itemgetter (1), elements))' eski davranışı işler.
Maik Beckmann

12

Bunu, 2 tuple listesinin ikinci öğesini çekmenin en hızlı yolunu ararken buldum. İstediğim şey değil ama 3. yöntemle gösterilen testin aynısını yaptım ve zip yöntemini test et

setup = 'elements = [(1,1) for _ in range(100000)];from operator import itemgetter'
method1 = '[x[1] for x in elements]'
method2 = 'map(itemgetter(1), elements)'
method3 = 'dict(elements).values()'
method4 = 'zip(*elements)[1]'

import timeit
t = timeit.Timer(method1, setup)
print('Method 1: ' + str(t.timeit(100)))
t = timeit.Timer(method2, setup)
print('Method 2: ' + str(t.timeit(100)))
t = timeit.Timer(method3, setup)
print('Method 3: ' + str(t.timeit(100)))
t = timeit.Timer(method4, setup)
print('Method 4: ' + str(t.timeit(100)))

Method 1: 0.618785858154
Method 2: 0.711684942245
Method 3: 0.298138141632
Method 4: 1.32586884499

Yani bir dikteye dönüştürmek ve değerleri almak için 2 demet çiftiniz varsa iki kat daha hızlı.


Muhtemelen bu açıktır, ancak dict(elements).values()liste karşılaştırması veya haritanın aksine tek öğeli diktle sonuçlanacağını belirtmek isterim. Bu tam olarak istediğim şeydi (benzersiz touple'larla ilgileniyordum) (+1 ve gönderdiğiniz için çok teşekkürler) ancak diğerleri dict'in neden daha hızlı olduğunu merak edebilir - bu bellek ayırmak değil, sadece mevcut öğeye karşı kontrol yapmak.
Greg0ry

6

Python 3.6 için, ikinci öğeyi 2 parçalı listeden çıkarmak için zamanlamalar .

Ayrıca, numpyokunması daha basit (ancak listeyi anlamadan tartışmasız daha basit) dizi yöntemi eklendi .

from operator import itemgetter
elements = [(1,1) for _ in range(100000)]

%timeit second = [x[1] for x in elements]
%timeit second = list(map(itemgetter(1), elements))
%timeit second = dict(elements).values()
%timeit second = list(zip(*elements))[1]
%timeit second = np.array(elements)[:,1]

ve zamanlamalar:

list comprehension:  4.73 ms ± 206 µs per loop
list(map):           5.3 ms ± 167 µs per loop
dict:                2.25 ms ± 103 µs per loop
list(zip)            5.2 ms ± 252 µs per loop
numpy array:        28.7 ms ± 1.88 ms per loop

Bunu unutmayın map()ve zip()artık bir liste döndürmeyin, dolayısıyla açık dönüşüm.



1

Kullanılması isliceve chain.from_iterable:

>>> from itertools import chain, islice
>>> elements = [(1,1,1),(2,3,7),(3,5,10)]
>>> list(chain.from_iterable(islice(item, 1, 2) for item in elements))
[1, 3, 5]

Bu, birden fazla elemana ihtiyacınız olduğunda yararlı olabilir:

>>> elements = [(0, 1, 2, 3, 4, 5), 
                (10, 11, 12, 13, 14, 15), 
                (20, 21, 22, 23, 24, 25)]
>>> list(chain.from_iterable(islice(tuple_, 2, 5) for tuple_ in elements))
[2, 3, 4, 12, 13, 14, 22, 23, 24]
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.