我如何创建一个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
当前回答
如果您对性能感兴趣,我做了一个小的基准测试(使用我的库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)]
其他回答
这是一个简单的解决方案,它使用range函数从元素列表中选择替代元素。
注意:这只对偶数列表有效。
a_list = [1, 2, 3, 4, 5, 6]
empty_list = []
for i in range(0, len(a_list), 2):
empty_list.append(a_list[i] + a_list[i + 1])
print(empty_list)
# [3, 7, 11]
>>> 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']
一个简单的解决方案。
l = [1, 2, 3, 4, 5, 6] for i in range(0, len(l), 2): print str(l[i]), '+', str(l[i + 1]), '=', str(l[i] + l[i + 1])
经过优化的Python3解决方案在itertools食谱之一中给出:
import itertools
def grouper(iterable, n, fillvalue=None):
"Collect data into fixed-length chunks or blocks"
# grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx"
args = [iter(iterable)] * n
return itertools.zip_longest(*args, fillvalue=fillvalue)
这个问题的标题有误导性,你似乎在寻找连续的对,但如果你想遍历所有可能的对的集合,那么这样做是可行的:
for i,v in enumerate(items[:-1]):
for u in items[i+1:]: