在列表中迭代每两个元素

310

如何编写 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

6
针对重叠的一对元素:https://dev59.com/p2035IYBdhLWcg3wZ_Qt这个问题询问如何在Python中以一对一对的形式迭代一个列表。在迭代时,包括当前元素和下一个元素作为一对,以便可以在每个对之间进行比较或操作。 - user202729
1
下次避免将某些东西命名为'l',因为它很容易与数字1、字母I或竖线混淆。最好将其命名为List或L(如果你想节省空间)。 - Nadu
1
只需使用两个变量的循环: for i,k in zip(range(1,7)[0::2], range(1,7)[1::2]): print str(i), '+', str(k), '=', str(i+k) - Shrm
正如我在下面由@johnysweb选择的答案中提到的那样,现在可以使用海象运算符(3.8+)以简洁的方式来完成这个操作:for i, k in zip(_x := iter(mylist), _x): ... - Alex Just Alex
22个回答

9

有很多种方式可以做到这一点。例如:

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)]

list(zip(*[iter(lst)]*2))
>>>[(1, 2), (3, 4), (5, 6)]

3
这个解决方案太被低估了。没有外部方法且处理可能情况得当。向您致敬,先生。 - ciurlaro

4
你可以使用more_itertools包。
import more_itertools

lst = range(1, 7)
for i, j in more_itertools.chunked(lst, 2):
    print(f'{i} + {j} = {i+j}')

2

一个简单的方法:

[(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)]

最初的回答:如果您的数组长度和步长不匹配,则必须处理多余值。

2

在Python3中,我们可以通过使用itertools模块中的一个方法来优化解决方案。具体实现请参考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)

2

另一种更简洁的解决方案尝试

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

更多自定义选项

from collections.abc import Sized

def grouped(itr, n=2, /, truncate=True, fillvalue=None, strict=False, nofill=False):
    if strict:
        if isinstance(itr, Sized):
            if len(itr) % n != 0:
                raise ValueError(f"{len(itr)=} is not divisible by {n=}")
    itr = iter(itr)
    end = object()
    while True:
        vals = tuple(next(itr, end) for _ in range(n))
        if vals[-1] is end:
            if vals[0] is end:
                return
            if strict:
                raise ValueError("found extra stuff in iterable")
            if nofill:
                yield tuple(v for v in vals if v is not end)
                return
            if truncate:
                return
            yield tuple(v if v is not end else fillvalue for v in vals)
            return
        yield vals

就像在我的解决方案中一样,现在你需要捕获 StopIteration - mic_e
@mic_e 我正在使用带有默认值的 next,它不会引发 StopIteration - balki

2
这个问题的标题有误导性,你似乎在寻找连续的一对,但如果你想迭代所有可能的一对,那么可以使用以下代码:
for i,v in enumerate(items[:-1]):
        for u in items[i+1:]:

2

如果有需要帮助的人,这里提供了一个类似的解决方案,但是针对的是有重叠的配对问题(而不是互斥的配对)。

来自Python itertools文档

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)

1

使用类型化,您可以使用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

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]]

1

我觉得这是一个好地方,可以分享我的一般性结论,适用于n>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)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接