Как извлечь n-й элемент из списка кортежей в python?


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

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

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

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

seconds = [1, 3, 5]

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

6 71

6 ответов:

[x[1] for x in elements]

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

есть и другой способ. Вы также можете сделать это с помощью карта и 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 - это хорошо.

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

zip(*elements)[1]

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

увидеть его в действии:

>>> help(zip)

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

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 в аргументах для создания списка параметров функции...

нашел это, как я искал, какой путь является самым быстрым, чтобы вытащить второй элемент списка 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 кортеж пара просто конвертировать в дикт и принимать значения.

map (lambda x:(x[1]),elements)

времени Python 3.6 для извлечения второго элемента из списка 2-кортежа.

кроме того, добавил 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() больше не возвращайте список, следовательно, явное преобразование.