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

2022-01-19 00:00:00 python list iteration tuples

问题描述

问题很简单,我想迭代列表的每个元素和下一个成对的元素(用第一个包裹最后一个).

The problem is easy, I want to iterate over each element of the list and the next one in pairs (wrapping the last one with the first).

我想到了两种非pythonic的方法:

I've thought about two unpythonic ways of doing it:

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

和:

def pairs(lst):
    return zip(lst,lst[1:]+[lst[:1]])

预期输出:

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

有什么关于更 Pythonic 的方法的建议吗?也许有一个我没有听说过的预定义函数?

any suggestions about a more pythonic way of doing this? maybe there is a predefined function out there I haven't heard about?

还有一个更通用的 n-fold(使用三重奏、四重奏等,而不是对)版本可能会很有趣.

also a more general n-fold (with triplets, quartets, etc. instead of pairs) version could be interesting.


解决方案

我自己编写了元组通用版本,我喜欢第一个,因为它优雅简洁,我越看越觉得 Pythonic我......毕竟,有什么比一个带有 zip、星号参数扩展、列表推导、列表切片、列表连接和范围"的单行更 Pythonic 的?

I've coded myself the tuple general versions, I like the first one for it's ellegant simplicity, the more I look at it, the more Pythonic it feels to me... after all, what is more Pythonic than a one liner with zip, asterisk argument expansion, list comprehensions, list slicing, list concatenation and "range"?

def ntuples(lst, n):
    return zip(*[lst[i:]+lst[:i] for i in range(n)])

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

The itertools version should be efficient enough even for large lists...

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

还有一个用于不可索引序列的版本:

And a version for non-indexable sequences:

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

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

Anyway, thanks everybody for your suggestions! :-)

相关文章