2010-07-22 594 views
61

我想从元组列表中获取第n个元素。如何从python中的元组列表中提取第n个元素?

我有类似:

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

我只希望每个元组的第二个元素提取到一个列表:

seconds = [1, 3, 5] 

我知道,它可以与for循环进行,但我想知道是否有另一种方式,因为我有成千上万的元组。

回答

123
[x[1] for x in elements] 
23

我知道,它可以用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))) 

结果:

 
Method 1: 1.25699996948 
Method 2: 1.46600008011 

如果你需要迭代一个列表,那么使用for就可以了。

+0

一个小的补充:在python-3.x中,基准测试会显示map只需要几分之一毫秒。这是因为它会返回一个迭代器。 method2 ='list(map(itemgetter(1),elements))'呈现旧行为。 – 2011-05-13 11:59:31

+0

这应该是公认的答案。 – 2016-09-06 17:14:10

21

这也适用于:

zip(*elements)[1] 

(我主要是发布此,为了证明自己,我已经groked zip ...)

看到它在行动:

>>> help(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

并使用'** dict'创建关键字参数:'def test(foo = 3,bar = 3):return foo * bar' then'd = {'bar':9,'foo'= 12};打印测试(** d)' – 2010-07-22 12:58:58

+0

@Wayne Werner:是的。这些东西都只是被动的知识(我不经常使用它) - 但它是时刻提醒,所以你知道在哪里/什么寻找...... – 2010-07-22 13:14:53

+0

真实的故事 - 我发现,在我经常使用的任何东西足够的(Python,vim),我倾向于需要提醒我已经忘记的整齐/酷的功能,因为我不经常使用它们*。 – 2010-07-22 14:26:10

9

发现这是我在寻找它的方式是最快的拉第二个元素的2元组列表。不是我想要的,但跑了相同的测试,如图与3方法以及测试方法拉链

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对,只是转换到一个字典,并采取值。

+0

这可能是显而易见的,但我会提及'dict(elements).values() '将产生一元字典而不是列表comprahension或map。这正是我想要的(我对独特的关注点感兴趣)(+1和非常感谢张贴),但其他人可能会问为什么字典更快 - 它不会分配内存,而只是检查现有元素。 – Greg0ry 2016-12-21 13:34:07

2
map (lambda x:(x[1]),elements) 
+4

考虑添加一些解释。 – fedorqui 2014-10-08 13:44:09

0

计时为的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()再也不会返回一个列表,因此显式转换。

相关问题