我有时需要在Python中迭代一个列表,查看"current"元素和"next"元素.到目前为止,我已经完成了以下代码:
for current, next in zip(the_list, the_list[1:]):
# Do something
Run Code Online (Sandbox Code Playgroud)
这有效并且符合我的预期,但是有更多惯用或有效的方法来做同样的事情吗?
Raf*_*ird 121
以下是itertools模块文档中的相关示例:
import itertools
def pairwise(iterable):
"s -> (s0,s1), (s1,s2), (s2, s3), ..."
a, b = itertools.tee(iterable)
next(b, None)
return zip(a, b)
Run Code Online (Sandbox Code Playgroud)
对于Python 2,您需要itertools.izip而不是zip:
import itertools
def pairwise(iterable):
"s -> (s0,s1), (s1,s2), (s2, s3), ..."
a, b = itertools.tee(iterable)
next(b, None)
return itertools.izip(a, b)
Run Code Online (Sandbox Code Playgroud)
这是如何工作的:
首先,两个平行的迭代器,a和b被创建(在tee()呼叫),两者都指向原始迭代的第一个元素.第二个迭代器,b向前移动一步(next(b, None))调用).此时指向as0并b指向s1.双方a并b可以独立遍历原来迭代器-的izip函数接受两个迭代器,使对返回的元素,以相同的速度前进的两个迭代器.
一个警告:该tee()函数产生两个迭代器,它们可以相互独立地前进,但它需要付出代价.如果其中一个迭代器比另一个迭代器进一步前进,那么tee() 需要将消耗的元素保留在内存中,直到第二个迭代器也将它们联合起来(它不能"回放"原始迭代器).这里没关系,因为一个迭代器只比另一个迭代器领先一步,但一般来说这很容易以这种方式使用大量内存.
既然tee()可以使用n参数,这也可以用于两个以上的并行迭代器:
def threes(iterator):
"s -> (s0,s1,s2), (s1,s2,s3), (s2, s3,4), ..."
a, b, c = itertools.tee(iterator, 3)
next(b, None)
next(c, None)
next(c, None)
return zip(a, b, c)
Run Code Online (Sandbox Code Playgroud)
Ry-*_*Ry- 26
滚动你自己!
def pairwise(iterable):
it = iter(iterable)
a = next(it, None)
for b in it:
yield (a, b)
a = b
Run Code Online (Sandbox Code Playgroud)
Sve*_*ach 19
由于the_list[1:]实际上创建了整个列表的副本(不包括其第一个元素),并zip()在调用时立即创建元组列表,因此总共创建了三个列表副本.如果您的列表非常大,您可能更喜欢
from itertools import izip, islice
for current_item, next_item in izip(the_list, islice(the_list, 1, None)):
print(current_item, next_item)
Run Code Online (Sandbox Code Playgroud)
根本不复制列表.
Qui*_*tec 14
我只是把它拿出来,我很惊讶没有人想到枚举().
for (index, thing) in enumerate(the_list):
if index < len(the_list):
current, next_ = thing, the_list[index + 1]
#do something
Run Code Online (Sandbox Code Playgroud)
Rum*_*kin 13
通过索引迭代可以做同样的事情:
#!/usr/bin/python
the_list = [1, 2, 3, 4]
for i in xrange(len(the_list) - 1):
current_item, next_item = the_list[i], the_list[i + 1]
print(current_item, next_item)
Run Code Online (Sandbox Code Playgroud)
输出:
(1, 2)
(2, 3)
(3, 4)
Run Code Online (Sandbox Code Playgroud)
Xav*_*hot 11
在即将到来的Python 3.10 release schedule,这是该pairwise功能的确切作用:
from itertools import pairwise
list(pairwise([1, 2, 3, 4, 5]))
# [(1, 2), (2, 3), (3, 4), (4, 5)]
Run Code Online (Sandbox Code Playgroud)
或者只是pairwise([1, 2, 3, 4, 5])如果您不需要结果作为list.
我真的很惊讶没有人提到更短、更简单且最重要的通用解决方案:
Python 3:
from itertools import islice
def n_wise(iterable, n):
return zip(*(islice(iterable, i, None) for i in range(n)))
Run Code Online (Sandbox Code Playgroud)
Python 2:
from itertools import izip, islice
def n_wise(iterable, n):
return izip(*(islice(iterable, i, None) for i in xrange(n)))
Run Code Online (Sandbox Code Playgroud)
它通过传递 来进行成对迭代n=2,但可以处理任何更高的数字:
>>> for a, b in n_wise('Hello!', 2):
>>> print(a, b)
H e
e l
l l
l o
o !
>>> for a, b, c, d in n_wise('Hello World!', 4):
>>> print(a, b, c, d)
H e l l
e l l o
l l o
l o W
o W o
W o r
W o r l
o r l d
r l d !
Run Code Online (Sandbox Code Playgroud)