it-swarm.com.de

Wie extrahiere ich die n-ten Elemente aus einer Liste von Tupeln?

Ich versuche, die n-ten Elemente aus einer Liste von Tupeln zu erhalten.

Ich habe so etwas wie:

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

Ich möchte nur die zweiten Elemente jedes Tupels in eine Liste extrahieren:

seconds = [1, 3, 5]

Ich weiß, dass dies mit einer for-Schleife möglich ist, aber ich wollte wissen, ob es einen anderen Weg gibt, da ich Tausende von Tupeln habe.

79
[x[1] for x in elements]
148
luc

Ich weiß, dass es mit einem FOR möglich ist, aber ich wollte wissen, ob es einen anderen Weg gibt 

Es geht auch anders. Sie können es auch mit map und itemgetter machen:

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

Dies führt jedoch intern immer noch eine Schleife aus und ist etwas langsamer als das Listenverständnis:

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)))

Ergebnisse:

 Methode 1: 1.25699996948 
 Methode 2: 1.46600008011 

Wenn Sie eine Liste durchlaufen müssen, ist die Verwendung einer for in Ordnung.

26
Mark Byers

Das funktioniert auch:

Zip(*elements)[1]

(Ich poste dies hauptsächlich, um mir zu beweisen, dass ich Zip... geärgert habe)

Sehen Sie es in Aktion:

>>> help(Zip)

Hilfe zur eingebauten Funktion Zip in module builtin :

Postleitzahl(...)

Zip (seq1 [ seq2 [...]]) -> [(seq1 [0], seq2 [0] ...), (...)]

Gibt eine Liste von Tupeln zurück, bei denen jeder Tupel das i-te Element enthält von jeder der Argumentsequenzen. Die zurückgegebene Liste wird abgeschnitten in Länge auf die Länge der kürzesten Argumentsequenz.

>>> 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)
>>>

Was ich heute gelernt habe: Verwenden Sie *list in Argumenten, um eine Parameterliste für eine Funktion zu erstellen ...

Note: In Python3 gibt Zip einen Iterator zurück. Verwenden Sie stattdessen list(Zip(*elements)), um eine Liste von Tupeln zurückzugeben.

24
Daren Thomas

Ich habe dies gefunden, als ich suchte, welcher Weg am schnellsten zum zweiten Element einer 2-Tuple-Liste führt. Nicht das, was ich wollte, aber den gleichen Test wie bei einer 3. Methode ausgeführt und die Zip-Methode getestet

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

Also über doppelt so schnell, wenn Sie ein 2-Tuple-Paar haben, das Sie einfach in ein Diktat konvertieren und die Werte übernehmen können.

11
Graeme Gellatly
map (lambda x:(x[1]),elements)
3
Thras

Timings für Python 3.6 zum Extrahieren des zweiten Elements aus einer 2-Tuple-Liste. 

Außerdem wurde die numpy-Array-Methode hinzugefügt, die einfacher zu lesen ist (aber möglicherweise einfacher als das Listenverständnis).

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]

und die Zeiten:

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

Beachten Sie, dass map() und Zip() keine Liste mehr zurückgeben, daher die explizite Konvertierung.

2
Oleg

islice und chain.from_iterable verwenden:

>>> 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]

Dies kann nützlich sein, wenn Sie mehr als ein Element benötigen:

>>> 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]
1
Georgy