问题:在Python中将列表成对迭代(当前,下一个)
有时我需要在Python中迭代一个列表,以查看“当前”元素和“下一个”元素。到目前为止,我已经使用以下代码完成了此操作:
for current, next in zip(the_list, the_list[1:]):
# Do something
这行得通,符合我的期望,但是有没有一种更惯用或有效的方式来执行相同的操作?
回答 0
这是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)
对于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)
工作原理:
首先,创建两个并行的迭代器,a
并将b
它们(tee()
称为调用)都指向原始可迭代的第一个元素。第二个迭代器b
向前移动1个(next(b, None)
)调用。此时指向a
s0并b
指向s1。双方a
并b
可以独立遍历原来迭代器-的izip函数接受两个迭代器,使对返回的元素,以相同的速度前进的两个迭代器。
一个警告:该tee()
函数产生两个可以彼此独立进行的迭代器,但这要付出一定的代价。如果一个迭代器比另一个迭代器前进得更多,则tee()
需要将消耗的元素保留在内存中,直到第二个迭代器也将它们消耗掉为止(它不能“倒回”原始迭代器)。这里没有关系,因为一个迭代器仅比另一个迭代器领先1步,但是通常很容易以这种方式使用大量内存。
而且由于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)
回答 1
自己滚!
def pairwise(iterable):
it = iter(iterable)
a = next(it, None)
for b in it:
yield (a, b)
a = b
回答 2
由于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)
根本不会复制列表。
回答 3
我只是将其列出来,我很惊讶没有人想到enumerate()。
for (index, thing) in enumerate(the_list):
if index < len(the_list):
current, next_ = thing, the_list[index + 1]
#do something
回答 4
通过索引进行迭代可以做同样的事情:
#!/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)
输出:
(1, 2)
(2, 3)
(3, 4)
回答 5
截至2020年5月16日,这现在是一个简单的导入
from more_itertools import pairwise
for current, next in pairwise(your_iterable):
print(f'Current = {current}, next = {nxt}')
更多itertools的文档 该代码与其他答案中的代码相同,但我更喜欢在可用时导入。
如果尚未安装,则:
pip install more-itertools
例
例如,如果您有fibbonnacci序列,则可以计算后续对的比率为:
from more_itertools import pairwise
fib= [1,1,2,3,5,8,13]
for current, nxt in pairwise(fib):
ratio=current/nxt
print(f'Curent = {current}, next = {nxt}, ratio = {ratio} ')
回答 6
使用列表理解从列表中配对
the_list = [1, 2, 3, 4]
pairs = [[the_list[i], the_list[i + 1]] for i in range(len(the_list) - 1)]
for [current_item, next_item] in pairs:
print(current_item, next_item)
输出:
(1, 2)
(2, 3)
(3, 4)
回答 7
我真的很惊讶,没有人提到更短,更简单,最重要的通用解决方案:
Python 3:
from itertools import islice
def n_wise(iterable, n):
return zip(*(islice(iterable, i, None) for i in range(n)))
Python 2:
from itertools import izip, islice
def n_wise(iterable, n):
return izip(*(islice(iterable, i, None) for i in xrange(n)))
它可以通过进行成对迭代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 !
回答 8
基本解决方案:
def neighbors( list ):
i = 0
while i + 1 < len( list ):
yield ( list[ i ], list[ i + 1 ] )
i += 1
for ( x, y ) in neighbors( list ):
print( x, y )
回答 9
code = '0016364ee0942aa7cc04a8189ef3'
# Getting the current and next item
print [code[idx]+code[idx+1] for idx in range(len(code)-1)]
# Getting the pair
print [code[idx*2]+code[idx*2+1] for idx in range(len(code)/2)]