在Python列表中遍历相邻的项目对

146

在Python中是否可以以以下方式迭代列表(将此代码视为伪代码)?

a = [5, 7, 11, 4, 5]
for v, w in a:
    print [v, w]

它应该产生

[5, 7]
[7, 11]
[11, 4]
[4, 5]
6个回答

218

您可以使用自身不包括第一个元素的列表进行zip

a = [5, 7, 11, 4, 5]

for previous, current in zip(a, a[1:]):
    print(previous, current)

即使您的列表没有元素或只有一个元素(在这种情况下,zip 返回一个空的可迭代对象,并且 for 循环中的代码永远不会执行),此方法仍然有效。但它不能用于生成器,只能用于序列 (例如 tupleliststr 等)。


4
这样不起作用。你正在迭代的每个单独列表都没有足够地“跳过”下一个记录,因此你的示例输出如下:[5, 7] [7, 11] [11, 4] [4, 5] - Brad
19
但这正是我们想要的结果,不是吗? - hluk
6
嗯...是的-我认为发帖者在寻找它-尽管我看到"pairwise"迭代返回像[5,7],[11,4],[5,None]这样的结果 - Brad
46
针对这个案例,zip(a[::2], a[1::2])会同时遍历两个列表,每次跨度为2。 - Evgeni Sergeev

124

来自itertools工具集:

from itertools import tee

def pairwise(iterable):
    "s -> (s0,s1), (s1,s2), (s2, s3), ..."
    a, b = tee(iterable)
    next(b, None)
    return zip(a, b)

for v, w in pairwise(a):
    ...

5
区别在于它适用于迭代器而不仅限于序列。虽然这并非必需,但你很难把它称作过度设计。我只是更喜欢使用迭代器,因为我一直在和它们打交道。 - Jochen Ritzel
5
如果你对从列表 a 中获取循环配对感兴趣,只需执行以下操作:pairwise(a + [a[0]]) - 0 _
7
注意:对于那些找到这个内容的人,这个方法适用于迭代器的优势在于它不需要随机访问数据流(例如数组访问);相反,它只需要一次摄取每个项目,并将其缓存以供下一次评估。因此,如果你有一个类似 Twitter 火管道的东西,你不需要将火管道读入一个庞大(可能是无限长度)的数组中才能使它工作。 - btown
1
如果可迭代的基数是奇数,这个解决方案不会删除最后一个元素,与zip函数不同。 - user305883
8
在Python 3.10中,你可以使用 itertools.pairwise:https://docs.python.org/3/library/itertools.html#itertools.pairwise - nimble_ninja
显示剩余4条评论

62

要做到这一点,您应该执行:

a =  [5, 7, 11, 4, 5]
for i in range(len(a)-1):
    print [a[i], a[i+1]]

4
在Python中,按索引引用列表项有点反模式(除非必须按顺序访问项)。请参见 https://github.com/JeffPaine/beautiful_idiomatic_python#looping-over-a-collection。 - Ian Goldby

18

5
空列表在执行i.next()时会引发StopIteration异常。 - 0 _
已在Py2.x和3.x中测试过,可以正常运行。 - ideasman42
为了解决空列表问题,请将第三行用 try: except StopIteration: return 包装起来。 - XCanG

9

另一种方法是使用 itertools.pairwise(Python 3.10 或更高版本):

from itertools import pairwise

temp = [-39.5, -27.5, -15.5, -3.5, 8.5, 20.5, 32.5, 44.5, 56.5, 68.5, 80.5, 92.5,104.5]
res = list(pairwise(temp))

[(-39.5, -27.5), (-27.5, -15.5), (-15.5, -3.5), (-3.5, 8.5), (8.5, 20.5), (20.5, 32.5), (32.5, 44.5), (44.5, 56.5), (56.5, 68.5), (68.5, 80.5), (80.5, 92.5), (92.5, 104.5)]

7
>>> a = [5, 7, 11, 4, 5]
>>> for n,k in enumerate(a[:-1]):
...     print a[n],a[n+1]
...
5 7
7 11
11 4
4 5

9
如果你不使用“k”,为什么要使用“enumerate”? - endolith
我猜是因为我们需要索引。 - Tanin
7
那么 for n i range(len(a)): 不是更准确和符合惯用语吗? - Daniel Standage
2
是的,range(len(a) - 1) 更好。 - Tanin

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