【发布时间】:2011-03-19 11:55:28
【问题描述】:
我正在尝试从元组列表中获取第 n 个元素。
我有类似的东西:
elements = [(1,1,1),(2,3,7),(3,5,10)]
我希望只将每个元组的第二个元素提取到一个列表中:
seconds = [1, 3, 5]
我知道这可以通过 for 循环来完成,但我想知道是否还有其他方法,因为我有数千个元组。
【问题讨论】:
我正在尝试从元组列表中获取第 n 个元素。
我有类似的东西:
elements = [(1,1,1),(2,3,7),(3,5,10)]
我希望只将每个元组的第二个元素提取到一个列表中:
seconds = [1, 3, 5]
我知道这可以通过 for 循环来完成,但我想知道是否还有其他方法,因为我有数千个元组。
【问题讨论】:
n = 1 # N. . .
[x[n] for x in elements]
【讨论】:
这也有效:
zip(*elements)[1]
(我发这个主要是为了证明我已经摸到了zip...)
查看实际操作:
>>> help(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 为函数创建参数列表...
注意:在 Python3 中,zip 返回一个迭代器,因此请改用 list(zip(*elements)) 返回一个元组列表。
【讨论】:
**dict 创建关键字参数:def test(foo=3, bar=3): return foo*bar 然后d = {'bar': 9, 'foo'=12}; print test(**d)
我知道可以用 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)))
结果:
方法一:1.25699996948 方法二:1.46600008011如果您需要遍历一个列表,那么使用 for 就可以了。
【讨论】:
在我搜索哪种方式可以最快地提取 2 元组列表的第二个元素时发现了这一点。不是我想要的,但运行与第三种方法相同的测试并测试 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() 将导致单元素字典,而不是列表综合或映射。这正是我想要的(我对独特的 touples 感兴趣)(+1 非常感谢您的发帖)但其他人可能想知道为什么 dict 更快 - 它不是分配内存,而是仅检查现有元素。
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() 不再返回列表,因此进行了显式转换。
【讨论】:
dict().values() 也需要list。
map (lambda x:(x[1]),elements)
【讨论】:
使用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]
【讨论】: