如何制作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
答案 0 :(得分:202)
您需要 pairwise()
(或 grouped()
)实施。
对于Python 2:
from itertools import izip
def pairwise(iterable):
"s -> (s0, s1), (s2, s3), (s4, s5), ..."
a = iter(iterable)
return izip(a, a)
for x, y in pairwise(l):
print "%d + %d = %d" % (x, y, x + y)
或者,更一般地说:
from itertools import izip
def grouped(iterable, n):
"s -> (s0,s1,s2,...sn-1), (sn,sn+1,sn+2,...s2n-1), (s2n,s2n+1,s2n+2,...s3n-1), ..."
return izip(*[iter(iterable)]*n)
for x, y in grouped(l, 2):
print "%d + %d = %d" % (x, y, x + y)
在Python 3中,您可以使用内置的izip
函数替换zip()
,然后删除import
。
对于martineau到his answer的my question的所有功劳,我发现这非常有效,因为它只在列表上迭代一次,并且在此过程中不会创建任何不必要的列表。
NB :这不应与Python pairwise
recipe中的itertools
documentation混淆,@lazyr会产生s -> (s0, s1), (s1, s2), (s2, s3), ...
,{{3}}指出在评论中。
答案 1 :(得分:153)
你需要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]
表示创建(index % 2 == 0)
zip(x,y)
从x和y集合创建一个元组集合,使用相同的索引元素。答案 2 :(得分:63)
>>> 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']
答案 3 :(得分:54)
一个简单的解决方案。
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])
答案 4 :(得分:37)
虽然使用zip
的所有答案都是正确的,但我发现自己实现这些功能会带来更易读的代码:
def pairwise(it):
it = iter(it)
while True:
yield next(it), next(it)
it = iter(it)
部分确保it
实际上是一个迭代器,而不仅仅是一个迭代器。如果it
已经是迭代器,则该行是无操作。
用法:
for a, b in pairwise([0, 1, 2, 3, 4, 5]):
print(a + b)
答案 5 :(得分:13)
为迟到而道歉。我希望这将是更优雅的做法。
a = [1,2,3,4,5,6]
zip(a[::2], a[1::2])
[(1, 2), (3, 4), (5, 6)]
答案 6 :(得分:12)
如果您对性能感兴趣,我会做一个小基准测试(使用我的库simple_benchmark
)来比较解决方案的性能,并且我在其中一个软件包中包含了一个函数:{{ 3}}
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提供的方法(在撰写本文时,它是最受欢迎和最受欢迎的答案)。
如果你不介意额外的依赖关系,那么来自grouper
的{{1}}可能会更快一点。
有些方法有一些限制,这里没有讨论过。
例如,一些解决方案仅适用于序列(即列表,字符串等),例如Margus / pyanon / taskinoor解决方案,它使用索引,而其他解决方案适用于任何可迭代(即序列和< / strong> generator,iterators)就像Johnysweb / mic_e / my solutions。
然后,Johnysweb还提供了一个解决方案,适用于2以外的其他尺寸,而其他答案不适用(好吧,iteration_utilities
也允许将元素数量设置为&#34; group&#34; )。
然后还有一个问题,即如果列表中有奇数个元素会发生什么。剩下的项目应该被解雇吗?列表是否应该填充以使其大小均匀?剩下的物品应该单独归还吗?另一个答案没有直接解决这一点,但是如果我没有忽略任何事情,他们都会遵循剩下的项目应该被解雇的方法(除了taskinoors的答案 - 这实际上会引发异常)。 / p>
使用iteration_utilities.grouper
,您可以决定要执行的操作:
grouper
答案 7 :(得分:9)
for (i, k) in zip(l[::2], l[1::2]):
print i, "+", k, "=", i+k
zip(*iterable)
返回一个元组,其中包含每个iterable的下一个元素。
l[::2]
返回列表的第1个,第3个,第5个等元素:第一个冒号表示切片从头开始,因为它后面没有数字,只有第二个冒号才需要你想要一个'切片中的一步'(在这种情况下为2)。
l[1::2]
执行相同的操作,但从列表的第二个元素开始,因此它返回原始列表的第2个,第4个,第6个等元素。
答案 8 :(得分:9)
同时使用zip
和iter
命令:
我发现使用iter
的解决方案非常优雅:
it = iter(l)
list(zip(it, it))
# [(1, 2), (3, 4), (5, 6)]
我在Python 3 zip documentation中找到了。
it = iter(l)
print(*(f'{u} + {v} = {u+v}' for u, v in zip(it, it)), sep='\n')
# 1 + 2 = 3
# 3 + 4 = 7
# 5 + 6 = 11
一次推广到N
个元素:
N = 2
list(zip(*([iter(l)] * N)))
# [(1, 2), (3, 4), (5, 6)]
答案 9 :(得分:4)
带包装:
l = [1,2,3,4,5,6]
while l:
i, k, *l = l
print(str(i), '+', str(k), '=', str(i+k))
答案 10 :(得分:2)
有很多方法可以做到这一点。例如:
lst = [1,2,3,4,5,6]
[(lst[i], lst[i+1]) for i,_ in enumerate(lst[:-1])]
>>>[(1, 2), (2, 3), (3, 4), (4, 5), (5, 6)]
[i for i in zip(*[iter(lst)]*2)]
>>>[(1, 2), (3, 4), (5, 6)]
答案 11 :(得分:2)
对于任何可能有帮助的人,这里是一个类似问题的解决方案,但有重叠对(而不是互斥对)。
来自Python itertools documentation:
from itertools import izip
def pairwise(iterable):
"s -> (s0,s1), (s1,s2), (s2, s3), ..."
a, b = tee(iterable)
next(b, None)
return izip(a, b)
或者,更一般地说:
from itertools import izip
def groupwise(iterable, n=2):
"s -> (s0,s1,...,sn-1), (s1,s2,...,sn), (s2,s3,...,sn+1), ..."
t = tee(iterable, n)
for i in range(1, n):
for j in range(0, i):
next(t[i], None)
return izip(*t)
答案 12 :(得分:1)
您可以使用more_itertools包。
import more_itertools
lst = range(1, 7)
for i, j in more_itertools.chunked(lst, 2):
print(f'{i} + {j} = {i+j}')
答案 13 :(得分:1)
另一种尝试更清洁的解决方案
def grouped(itr, n=2):
itr = iter(itr)
end = object()
while True:
vals = tuple(next(itr, end) for _ in range(n))
if vals[-1] is end:
return
yield vals
答案 14 :(得分:1)
我需要将列表除以数字,然后像这样固定。
l = [1,2,3,4,5,6]
def divideByN(data, n):
return [data[i*n : (i+1)*n] for i in range(len(data)//n)]
>>> print(divideByN(l,2))
[[1, 2], [3, 4], [5, 6]]
>>> print(divideByN(l,3))
[[1, 2, 3], [4, 5, 6]]
答案 15 :(得分:0)
使用输入法,以便您可以使用mypy静态分析工具来验证数据:
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
答案 16 :(得分:0)
一种简单的方法:
[(a[i],a[i+1]) for i in range(0,len(a),2)]
如果您的数组是a并且您想成对迭代它,这将很有用。 要迭代三胞胎或更多,只需更改“ range”步骤命令,例如:
[(a[i],a[i+1],a[i+2]) for i in range(0,len(a),3)]
(如果数组长度和步长不合适,则必须处理多余的值)
答案 17 :(得分:0)
这个问题的标题是误导性的,你似乎在寻找连续的对,但如果你想迭代所有可能的对的集合,那么这将起作用:
for i,v in enumerate(items[:-1]):
for u in items[i+1:]:
答案 18 :(得分:0)
认为这是一个分享我对n&gt; 2的概括的好地方,这只是一个可迭代的滑动窗口:
def sliding_window(iterable, n):
its = [ itertools.islice(iter, i, None)
for i, iter
in enumerate(itertools.tee(iterable, n)) ]
return itertools.izip(*its)
答案 19 :(得分:0)
优美的Python3解决方案在itertools
recipes之一中给出:
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)
答案 20 :(得分:-1)
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)
答案 21 :(得分:-1)
这里我们可以使用alt_elem
方法,它可以适合你的for循环。
def alt_elem(list, index=2):
for i, elem in enumerate(list, start=1):
if not i % index:
yield tuple(list[i-index:i])
a = range(10)
for index in [2, 3, 4]:
print("With index: {0}".format(index))
for i in alt_elem(a, index):
print(i)
输出:
With index: 2
(0, 1)
(2, 3)
(4, 5)
(6, 7)
(8, 9)
With index: 3
(0, 1, 2)
(3, 4, 5)
(6, 7, 8)
With index: 4
(0, 1, 2, 3)
(4, 5, 6, 7)
注意:考虑到在func中执行的操作,上述解决方案可能效率不高。