我如何创建一个for循环或一个列表推导式,以便每次迭代都给我两个元素?
l = [1,2,3,4,5,6]
for i,k in ???:
print str(i), '+', str(k), '=', str(i+k)
输出:
1+2=3
3+4=7
5+6=11
我如何创建一个for循环或一个列表推导式,以便每次迭代都给我两个元素?
l = [1,2,3,4,5,6]
for i,k in ???:
print str(i), '+', str(k), '=', str(i+k)
输出:
1+2=3
3+4=7
5+6=11
当前回答
使用类型,以便您可以使用myypy静态分析工具验证数据:
from typing import Iterator, Any, Iterable, TypeVar, Tuple
T_ = TypeVar('T_')
Pairs_Iter = Iterator[Tuple[T_, T_]]
def legs(iterable: Iterator[T_]) -> Pairs_Iter:
begin = next(iterable)
for end in iterable:
yield begin, end
begin = end
其他回答
简单的方法:
[(a[i],a[i+1]) for i in range(0,len(a),2)]
如果你的数组是a,并且你想成对迭代它,这是很有用的。 要迭代三胞胎或更多,只需更改"range" step命令,例如:
[(a[i],a[i+1],a[i+2]) for i in range(0,len(a),3)]
(如果你的数组长度和步长不匹配,你必须处理多余的值)
>>> l = [1,2,3,4,5,6]
>>> zip(l,l[1:])
[(1, 2), (2, 3), (3, 4), (4, 5), (5, 6)]
>>> zip(l,l[1:])[::2]
[(1, 2), (3, 4), (5, 6)]
>>> [a+b for a,b in zip(l,l[1:])[::2]]
[3, 7, 11]
>>> ["%d + %d = %d" % (a,b,a+b) for a,b in zip(l,l[1:])[::2]]
['1 + 2 = 3', '3 + 4 = 7', '5 + 6 = 11']
你需要2个元素的元组
data = [1,2,3,4,5,6]
for i,k in zip(data[0::2], data[1::2]):
print str(i), '+', str(k), '=', str(i+k)
地点:
Data[0::2]表示创建元素的子集集合(索引% 2 == 0) Zip (x,y)从x和y集合中创建一个相同索引元素的元组集合。
如果您对性能感兴趣,我做了一个小的基准测试(使用我的库simple_benchmark)来比较解决方案的性能,并且我包含了一个来自我的包的函数:iteration_utilities.grouper
from iteration_utilities import grouper
import matplotlib as mpl
from simple_benchmark import BenchmarkBuilder
bench = BenchmarkBuilder()
@bench.add_function()
def Johnsyweb(l):
def pairwise(iterable):
"s -> (s0, s1), (s2, s3), (s4, s5), ..."
a = iter(iterable)
return zip(a, a)
for x, y in pairwise(l):
pass
@bench.add_function()
def Margus(data):
for i, k in zip(data[0::2], data[1::2]):
pass
@bench.add_function()
def pyanon(l):
list(zip(l,l[1:]))[::2]
@bench.add_function()
def taskinoor(l):
for i in range(0, len(l), 2):
l[i], l[i+1]
@bench.add_function()
def mic_e(it):
def pairwise(it):
it = iter(it)
while True:
try:
yield next(it), next(it)
except StopIteration:
return
for a, b in pairwise(it):
pass
@bench.add_function()
def MSeifert(it):
for item1, item2 in grouper(it, 2):
pass
bench.use_random_lists_as_arguments(sizes=[2**i for i in range(1, 20)])
benchmark_result = bench.run()
mpl.rcParams['figure.figsize'] = (8, 10)
benchmark_result.plot_both(relative_to=MSeifert)
所以,如果你想要一个没有外部依赖的最快的解决方案,你可能应该使用Johnysweb给出的方法(在撰写本文时,它是得到最多好评和接受的答案)。
如果您不介意额外的依赖关系,那么来自iteration_utilities的grouper可能会更快一些。
额外的想法
有些方法有一些限制,这里没有讨论。
例如,一些解决方案只适用于序列(即列表,字符串等),例如Margus/pyanon/taskinoor解决方案使用索引,而其他解决方案适用于任何可迭代对象(即序列和生成器,迭代器),如Johnysweb/mic_e/my解决方案。
然后Johnysweb还提供了一个解决方案,它适用于其他大于2的大小,而其他答案则不适用(好吧,iteration_utilities。Grouper还允许将元素的数量设置为“group”)。
然后还有一个问题,如果列表中有奇数个元素,会发生什么。剩余的项目是否应该取消?是否应该填充列表以使其大小相等?剩余的物品是否要单独退回?其他答案没有直接解决这一点,但是如果我没有忽略任何东西,他们都遵循剩余的项目应该被驳回的方法(除了taskinoors的答案-这实际上会引发一个异常)。
对于石斑鱼,你可以决定你想做什么:
>>> from iteration_utilities import grouper
>>> list(grouper([1, 2, 3], 2)) # as single
[(1, 2), (3,)]
>>> list(grouper([1, 2, 3], 2, truncate=True)) # ignored
[(1, 2)]
>>> list(grouper([1, 2, 3], 2, fillvalue=None)) # padded
[(1, 2), (3, None)]
拆包:
l = [1,2,3,4,5,6]
while l:
i, k, *l = l
print(f'{i}+{k}={i+k}')
注意:这将消耗l,之后将其保留为空。