在Python中以列表(循环方式)迭代对

for*_*ran 35 python iteration tuples list

问题很简单,我想迭代遍历列表中的每个元素和成对的下一个元素(将最后一个元素包装在第一个元素中).

我想过两种非常规的方式:

def pairs(lst):
    n = len(lst)
    for i in range(n):
        yield lst[i],lst[(i+1)%n]
Run Code Online (Sandbox Code Playgroud)

和:

def pairs(lst):
    return zip(lst,lst[1:]+[lst[:1]])
Run Code Online (Sandbox Code Playgroud)

预期产量:

>>> for i in pairs(range(10)):
    print i

(0, 1)
(1, 2)
(2, 3)
(3, 4)
(4, 5)
(5, 6)
(6, 7)
(7, 8)
(8, 9)
(9, 0)
>>> 
Run Code Online (Sandbox Code Playgroud)

有关更多pythonic方式的任何建议吗?也许有一个我没有听说过的预定义功能?

也是一个更普遍的n折(有三胞胎,四重奏等代替对)版本可能很有趣.

Mar*_*wis 27

def pairs(lst):
    i = iter(lst)
    first = prev = item = i.next()
    for item in i:
        yield prev, item
        prev = item
    yield item, first
Run Code Online (Sandbox Code Playgroud)

适用于任何非空序列,无需索引.

  • @Darius,如果你需要支持空seq,在设置`sentinel = object()`之后使用`next(i,sentinel)`来代替老式的`i.next()`; 并且,`如果第一个是sentinel:return`就在`for`之前. (6认同)
  • 在1元素序列上崩溃:在调用`i.next()之后,序列为空,因此循环不绑定`item`,因此`yield item,first`引发`UnboundLocalError`. (2认同)

for*_*ran 9

我自己编写了元组通用版本,我喜欢第一个版本,因为它的优雅简洁,我看得越多,它对我的​​感觉就越多......毕竟,Pythonic比一个带拉链的内衬更多,星号参数扩展,列表推导,列表切片,列表连接和"范围"?

def ntuples(lst, n):
    return zip(*[lst[i:]+lst[:i] for i in range(n)])
Run Code Online (Sandbox Code Playgroud)

即使对于大型列表,itertools版本也应该足够高效...

from itertools import *
def ntuples(lst, n):
    return izip(*[chain(islice(lst,i,None), islice(lst,None,i)) for i in range(n)])
Run Code Online (Sandbox Code Playgroud)

以及非索引序列的版本:

from itertools import *
def ntuples(seq, n):
    iseq = iter(seq)
    curr = head = tuple(islice(iseq, n))
    for x in chain(iseq, head):
        yield curr
        curr = curr[1:] + (x,)
Run Code Online (Sandbox Code Playgroud)

无论如何,感谢大家的建议!:-)

  • 您的第一个答案(在您的问题中)比其中任何一个都容易理解一百万次.这使我的书中更加pythonic: - / (5认同)

pil*_*her 6

我一如既往地喜欢发球台:

from itertools import tee, izip, chain

def pairs(iterable):
    a, b = tee(iterable)
    return izip(a, chain(b, [next(b)]))
Run Code Online (Sandbox Code Playgroud)


hug*_*own 5

这可能是令人满意的:

def pairs(lst):
    for i in range(1, len(lst)):
        yield lst[i-1], lst[i]
    yield lst[-1], lst[0]

>>> a = list(range(5))
>>> for a1, a2 in pairs(a):
...     print a1, a2
...
0 1
1 2
2 3
3 4
4 0
Run Code Online (Sandbox Code Playgroud)

如果您喜欢这种东西,请查看wordaligned.org上的python文章.作者对python中的生成器特别喜欢.