Как извлечь n-й элемент из списка кортежей? - PullRequest
91 голосов
/ 22 июля 2010

Я пытаюсь получить n-й элемент из списка кортежей.

У меня есть что-то вроде:

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

Я хочу извлечь только вторые элементы каждогокортеж в список:

seconds = [1, 3, 5]

Я знаю, что это можно сделать с помощью цикла for, но я хотел знать, есть ли другой способ, поскольку у меня есть тысячи кортежей.

Ответы [ 7 ]

160 голосов
/ 22 июля 2010
n = 1 # N. . .
[x[n] for x in elements]
27 голосов
/ 22 июля 2010

Я знаю, что это можно сделать с помощью FOR, но я хотел знать, есть ли другой способ

Есть другой способ. Вы также можете сделать это с map и itemgetter :

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

Это все еще выполняет цикл внутри, и это немного медленнее, чем понимание списка:

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

Результаты:

Method 1: 1.25699996948
Method 2: 1.46600008011

Если вам нужно перебрать список, тогда можно использовать for.

25 голосов
/ 22 июля 2010

Это также работает:

zip(*elements)[1]

(я в основном публикую это, чтобы доказать себе, что я заколол zip ...)

Посмотри в действии:

>>> help(zip)

Справка по встроенной функции zip в модуле встроенный :

застежка-молния (...)

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

Возвращает список кортежей, где каждый кортеж содержит i-й элемент из каждой последовательности аргументов. Возвращенный список усекается по длине до длины самой короткой последовательности аргументов.

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

Изящная вещь, которую я узнал сегодня: используйте *list в аргументах, чтобы создать список параметров для функции ...

Примечание : в Python3 zip возвращает итератор, поэтому вместо него используйте list(zip(*elements)) для возврата списка кортежей.

11 голосов
/ 20 ноября 2012

Нашел это, когда искал, какой способ быстрее всего получить второй элемент списка из 2-х кортежей. Не то, что я хотел, но запустил тот же тест, как показано с 3-м методом, плюс тест по методу zip

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

Так что в два раза быстрее, если у вас есть пара кортежей из 2, чтобы просто преобразовать в dict и принять значения.

3 голосов
/ 05 января 2018

Время для Python 3.6 для извлечения второго элемента из списка из двух кортежей.

Кроме того, добавлен numpy метод массива, который проще для чтения (но, вероятно, проще, чем понимание списка).

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]

и время:

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

Обратите внимание, что map() и zip() больше не возвращают список, следовательно, явное преобразование.

3 голосов
/ 08 октября 2014
map (lambda x:(x[1]),elements)
1 голос
/ 27 января 2019

Использование islice и 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]

Это может быть полезно, когда вам нужно более одного элемента:

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