如何从元组列表中提取第n个元素?


112

我正在尝试从元组列表中获取第n个元素。

我有类似的东西:

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

我希望仅将每个元组的第二个元素提取到列表中:

seconds = [1, 3, 5]

我知道可以通过for循环来完成,但是我想知道是否有另一种方法,因为我有成千上万的元组。

Answers:



34

这也适用:

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))返回一个元组列表。


2
并用于**dict创建关键字参数:def test(foo=3, bar=3): return foo*bar然后d = {'bar': 9, 'foo'=12}; print test(**d)
Wayne Werner

@Wayne Werner:是的。这些东西全都是消极的知识(我不经常使用它)-但最好时不时提醒,以便您知道要寻找的位置/内容...
Daren Thomas,2010年

1
真实的故事-我发现,在任何我经常使用足够(Python和VIM),我倾向于利落/冷却的需要提醒的特点是我忘了,因为我不使用他们经常。
韦恩·维尔纳

* list语法非常有用。任何想法在官方python文档中有描述吗?
user1748155

我只发现它在教程:docs.python.org/2/tutorial/...
达人托马斯

30

我知道可以用FOR完成,但是我想知道是否还有其他方法

还有另一种方式。您也可以使用mapitemgetter来做到这一点:

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

结果:

方法1:1.25699996948
方法2:1.46600008011

如果您需要遍历列表,则可以使用a for


2
一个小小的补充:在python-3.x中,基准测试将显示地图仅需一毫秒的时间。那是因为它将返回一个迭代器。method2 ='list(map(itemetter(1),elements))'呈现旧行为。
迈克·贝克曼

12

我在寻找哪种方式最快地拉出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并取值就可以快两倍。


这可能是显而易见的,但我要提到的是dict(elements).values()将导致单元素dict而不是列表修饰或映射。这正是我想要的(我对独特的touples很感兴趣)(+ 1,并非常感谢您发帖),但是其他人可能想知道为什么dict更快-它不分配内存,而只是检查现有元素。
Greg0ry '16

6

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()不再返回列表,因此进行了显式转换。



1

使用islicechain.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]
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.