如何迭代列表中重叠的(当前、下一个)值对?

2024-11-22 08:47:00
admin
原创
181
摘要:问题描述:我有时需要在 Python 中迭代一个列表,查看“当前”元素和“下一个”元素。到目前为止,我已经使用以下代码完成了此操作:for current, next in zip(the_list, the_list[1:]): # Do something 这可以达到我的预期,但是有没有更惯用或更...

问题描述:

我有时需要在 Python 中迭代一个列表,查看“当前”元素和“下一个”元素。到目前为止,我已经使用以下代码完成了此操作:

for current, next in zip(the_list, the_list[1:]):
    # Do something

这可以达到我的预期,但是有没有更惯用或更有效的方法来做同样的事情?


这个问题的一些答案可以通过解决一次只取两个元素的具体情况来简化。对于一次取 N 个元素的一般情况,请参阅滚动或滑动窗口迭代器?。


解决方案 1:

3.8 的文档提供了这个配方:

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来获取相同类型的惰性迭代器(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和(调用),它们都指向原始可迭代对象的第一个元素。第二个迭代器向前移动 1 步(调用)。此时,它们指向 s0 和s1。和都可以独立遍历原始迭代器 - izip 函数采用这两个迭代器并对返回的元素进行配对,以相同的速度推进这两个迭代器。b`tee()bnext(b, None)abab`

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

警告:如果生成的迭代器之一tee比其他迭代器前进得更快,则实现需要将消耗的元素保留在内存中,直到每个迭代器都消耗了它们(它不能“倒回”原始迭代器)。这里这并不重要,因为一个迭代器仅比另一个迭代器领先一步,但通常这种方式很容易使用大量内存。

解决方案 2:

自己动手吧!

def pairwise(iterable):
    it = iter(iterable)
    a = next(it, None)

    for b in it:
        yield (a, b)
        a = b

解决方案 3:

从 Python 3.10 开始,该函数的确切作用如下pairwise

from itertools import pairwise

list(pairwise([1, 2, 3, 4, 5]))
# [(1, 2), (2, 3), (3, 4), (4, 5)]

或者简单地说,pairwise([1, 2, 3, 4, 5])如果您不需要结果作为list

解决方案 4:

我只是把这个说出来,我很惊讶没有人想到过 enumerate()。

for (index, thing) in enumerate(the_list):
    if index < len(the_list):
        current, next_ = thing, the_list[index + 1]
        #do something

解决方案 5:

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

它根本不复制列表。

解决方案 6:

通过索引迭代可以做同样的事情:

#!/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)

解决方案 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:

截至 2020 年 5 月 16 日,这是一个简单的导入

from more_itertools import pairwise
for current, next in pairwise(your_iterable):
  print(f'Current = {current}, next = {nxt}')

more-itertools 的文档
从本质上讲,此代码与其他答案中的代码相同,但我更喜欢在可用时导入。

如果你尚未安装,那么:
pip install more-itertools

例子

例如如果你有斐波那契数列,你可以计算后续对的比率:

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

解决方案 9:

正如其他人指出的那样,itertools.pairwise()这是 Python 最新版本的必经之路。但是,对于 3.8+ 版本,一个有趣且更简洁(与已发布的其他解决方案相比)的选项不需要额外的导入,它通过海象运算符实现:

def pairwise(iterable):
  a = next(iterable)
  yield from ((a, a := b) for b in iterable)

解决方案 10:

一个基本的解决方案:

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 )

解决方案 11:

使用列表推导式从列表中配对

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)

解决方案 12:

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]

li_tup = []
count=0
i=0
new_tup=()
while i<len(temp):
    if count<1:
        new_tup = new_tup + (temp[i],)
        count=count+1
        i=i+1
    else:
        new_tup = new_tup + (temp[i],)
        count=0
        li_tup.append(new_tup)
        new_tup=()
print(li_tup)

其中一种方法就是像上面那样

解决方案 13:

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)]
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1565  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1354  
  信创国产芯片作为信息技术创新的核心领域,对于推动国家自主可控生态建设具有至关重要的意义。在全球科技竞争日益激烈的背景下,实现信息技术的自主可控,摆脱对国外技术的依赖,已成为保障国家信息安全和产业可持续发展的关键。国产芯片作为信创产业的基石,其发展水平直接影响着整个信创生态的构建与完善。通过不断提升国产芯片的技术实力、产...
国产信创系统   21  
  信创生态建设旨在实现信息技术领域的自主创新和安全可控,涵盖了从硬件到软件的全产业链。随着数字化转型的加速,信创生态建设的重要性日益凸显,它不仅关乎国家的信息安全,更是推动产业升级和经济高质量发展的关键力量。然而,在推进信创生态建设的过程中,面临着诸多复杂且严峻的挑战,需要深入剖析并寻找切实可行的解决方案。技术创新难题技...
信创操作系统   27  
  信创产业作为国家信息技术创新发展的重要领域,对于保障国家信息安全、推动产业升级具有关键意义。而国产芯片作为信创产业的核心基石,其研发进展备受关注。在信创国产芯片的研发征程中,面临着诸多复杂且艰巨的难点,这些难点犹如一道道关卡,阻碍着国产芯片的快速发展。然而,科研人员和相关企业并未退缩,积极探索并提出了一系列切实可行的解...
国产化替代产品目录   28  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用