Iterating over every two elements in a list
如何进行
1 2 3 4 | l = [1,2,3,4,5,6] for i,k in ???: print str(i), '+', str(k), '=', str(i+k) |
输出:
1 2 3 | 1+2=3 3+4=7 5+6=11 |
号
您需要一个
对于python 2:
1 2 3 4 5 6 7 8 9 | 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) |
或者更一般地说:
1 2 3 4 5 6 7 8 | 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中,可以用内置的
感谢马蒂诺对我问题的回答,我发现这是非常有效的,因为它只在列表上迭代一次,并且在这个过程中不会创建任何不必要的列表。
注意:正如@lazyr在评论中指出的那样,这不应该与python自己的
你需要两个元素的元组,所以
1 2 3 | 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集合中创建一个元组集合,该集合与索引元素相同。
1 2 3 4 5 6 7 8 9 10 11 12 13 | >>> 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'] |
一个简单的解决方案。
1 2 3 4 | 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]) |
。
虽然所有使用
1 2 3 4 | def pairwise(it): it = iter(it) while True: yield next(it), next(it) |
。
用途:
1 2 | for a, b in pairwise([0, 1, 2, 3, 4, 5]): print(a + b) |
很抱歉迟到了。我希望这样做会更优雅。
1 2 3 4 | a = [1,2,3,4,5,6] zip(a[::2], a[1::2]) [(1, 2), (3, 4), (5, 6)] |
如果您对性能感兴趣,我做了一个小基准(使用我的库
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | 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给出的方法(在撰写本文的时候,这是最乐观和最可接受的答案)。
如果你不介意额外的依赖,那么来自
有些方法有一些限制,这里还没有讨论。
例如,一些解决方案只适用于序列(即列表、字符串等),例如margus/pyanon/taskinor解决方案使用索引,而其他解决方案则适用于任何可重复的(即序列和生成器、迭代器),如johnysweb/mic_e/my解决方案。
然后,johnysweb还提供了一个适用于2以外尺寸的解决方案,而其他答案则不适用(好吧,
还有一个问题,如果列表中元素的数目是奇数,那么应该发生什么。是否应取消剩余项?应该填充列表使其大小均匀吗?是否应将剩余项作为单个项返回?另一个答案并没有直接解决这一点,但是如果我没有忽略任何问题,他们都会遵循剩下的项目应该被取消的方法(除了taskinoors答案——这实际上会引发一个异常)。
使用
1 2 3 4 5 6 7 8 9 10 | >>> 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)] |
号
同时使用
我发现这个使用
1 2 3 | it = iter(l) list(zip(it, it)) # [(1, 2), (3, 4), (5, 6)] |
号
我在python 3 zip文档中找到的。
1 2 3 4 5 6 7 | it = iter(l) print(*(f'{u} + {v} = {u+v}' for u, v in zip(it, it)), sep=' ') # 1 + 2 = 3 # 3 + 4 = 7 # 5 + 6 = 11 |
号
一次概括为
1 2 3 | N = 2 list(zip(*([iter(l)] * N))) # [(1, 2), (3, 4), (5, 6)] |
号
1 2 | for (i, k) in zip(l[::2], l[1::2]): print i,"+", k,"=", i+k |
。
对于任何人来说,它可能会有所帮助,这里有一个解决类似问题的方法,但是使用重叠对(而不是互斥对)。
从python itertools文档中:
1 2 3 4 5 6 7 | 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) |
号
或者更一般地说:
1 2 3 4 5 6 7 8 9 | 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) |
号
您可以使用更多的工具包。
1 2 3 4 5 | import more_itertools lst = range(1, 7) for i, j in more_itertools.chunked(lst, 2): print(f'{i} + {j} = {i+j}') |
号
我需要用一个数字来划分一个列表,然后像这样固定。
1 2 3 4 5 6 7 8 9 10 | 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]] |
一种简单的方法:
1 | [(a[i],a[i+1]) for i in range(0,len(a),2)] |
。
如果您的数组是一个,并且您希望成对迭代它,那么这很有用。要迭代三元组或更多,只需更改"range"step命令,例如:
1 | [(a[i],a[i+1],a[i+2]) for i in range(0,len(a),3)] |
。
(如果数组长度和步骤不合适,则必须处理多余的值)
我认为这是一个很好的地方来分享我对n>2的概括,它只是一个滑动窗口在一个不可测的:
1 2 3 4 5 6 | def sliding_window(iterable, n): its = [ itertools.islice(iter, i, None) for i, iter in enumerate(itertools.tee(iterable, n)) ] return itertools.izip(*its) |
。
这个问题的标题是误导性的,您似乎在寻找连续的对,但是如果您想要迭代所有可能对的集合,那么这将起作用:
1 2 | for i,v in enumerate(items[:-1]): for u in items[i+1:]: |
号
使用键入,以便使用mypy静态分析工具验证数据:
1 2 3 4 5 6 7 8 9 10 | 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 |
1 2 3 4 5 | 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) |
。
这里我们可以有适合您的for循环的
1 2 3 4 5 6 7 8 9 10 11 | 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) |
。
输出:
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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中执行的操作,上述解决方案可能不高效。