来自单个列表的对 [重复]

2025-03-04 08:25:00
admin
原创
75
摘要:问题描述:我经常发现需要按对处理列表。我想知道哪种方式才是 Python 式且高效的处理方式,然后在 Google 上找到了这个:pairs = zip(t[::2], t[1::2]) 我认为这已经足够符合 Python 风格了,但是在最近一次涉及习语与效率的讨论之后,我决定做一些测试:import tim...

问题描述:

我经常发现需要按对处理列表。我想知道哪种方式才是 Python 式且高效的处理方式,然后在 Google 上找到了这个:

pairs = zip(t[::2], t[1::2])

我认为这已经足够符合 Python 风格了,但是在最近一次涉及习语与效率的讨论之后,我决定做一些测试:

import time
from itertools import islice, izip

def pairs_1(t):
    return zip(t[::2], t[1::2]) 

def pairs_2(t):
    return izip(t[::2], t[1::2]) 

def pairs_3(t):
    return izip(islice(t,None,None,2), islice(t,1,None,2))

A = range(10000)
B = xrange(len(A))

def pairs_4(t):
    # ignore value of t!
    t = B
    return izip(islice(t,None,None,2), islice(t,1,None,2))

for f in pairs_1, pairs_2, pairs_3, pairs_4:
    # time the pairing
    s = time.time()
    for i in range(1000):
        p = f(A)
    t1 = time.time() - s

    # time using the pairs
    s = time.time()
    for i in range(1000):
        p = f(A)
        for a, b in p:
            pass
    t2 = time.time() - s
    print t1, t2, t2-t1

以下是我的计算机上的结果:

1.48668909073 2.63187503815 1.14518594742
0.105381965637 1.35109519958 1.24571323395
0.00257992744446 1.46182489395 1.45924496651
0.00251388549805 1.70076990128 1.69825601578

如果我理解正确的话,那应该意味着 Python 中列表、列表索引和列表切片的实现非常高效。这个结果既令人欣慰又出乎意料。

是否有另一种“更好”的方法来成对遍历列表?

请注意,如果列表有奇数个元素,那么最后一个元素将不会出现在任何对中。

哪种方法才是正确的,可以确保包含所有元素?

我从测试答案中添加了以下两条建议:

def pairwise(t):
    it = iter(t)
    return izip(it, it)

def chunkwise(t, size=2):
    it = iter(t)
    return izip(*[it]*size)

以下是结果:

0.00159502029419 1.25745987892 1.25586485863
0.00222492218018 1.23795199394 1.23572707176

目前结果

最符合 Python 风格,且非常高效:

pairs = izip(t[::2], t[1::2])

最高效且非常 Python 化:

pairs = izip(*[iter(t)]*2)

我花了一段时间才明白,第一个答案使用了两个迭代器,而第二个答案只使用了一个迭代器。

为了处理具有奇数个元素的序列,建议在原始序列中添加一个元素(None),该元素与前一个元素配对,这可以通过实现itertools.izip_longest()

最后

请注意,在 Python 3.x 中,zip()行为如同itertools.izip(),并且itertools.izip() 已消失。


解决方案 1:

我最喜欢的方式是:

def pairwise(t):
    it = iter(t)
    return zip(it,it)

# for "pairs" of any length
def chunkwise(t, size=2):
    it = iter(t)
    return zip(*[it]*size)

当你想配对所有元素时你显然可能需要一个填充值:

from itertools import izip_longest
def blockwise(t, size=2, fillvalue=None):
    it = iter(t)
    return izip_longest(*[it]*size, fillvalue=fillvalue)

使用 Python 3,itertools.izip现在只需zip……使用较旧的 Python,使用

from itertools import izip as zip

解决方案 2:

我想说你的初始解决方案pairs = zip(t[::2], t[1::2])是最好的,因为它最容易阅读(并且在 Python 3 中,zip自动返回迭代器而不是列表)。

为了确保包含所有元素,您只需通过 扩展列表即可None

然后,如果列表有奇数个元素,则最后一对将是(item, None)

>>> t = [1,2,3,4,5]
>>> t.append(None)
>>> zip(t[::2], t[1::2])
[(1, 2), (3, 4), (5, None)]
>>> t = [1,2,3,4,5,6]
>>> t.append(None)
>>> zip(t[::2], t[1::2])
[(1, 2), (3, 4), (5, 6)]

解决方案 3:

我先从小免责声明开始 - 不要使用下面的代码。它根本不符合 Python 风格,我只是为了好玩而写的。它类似于 @THC4kpairwise函数,但它使用iterlambda包。它不使用itertools模块也不支持fillvalue。我把它放在这里是因为有人可能会觉得它很有趣:

pairwise = lambda t: iter((lambda f: lambda: (f(), f()))(iter(t).next), None)

解决方案 4:

就大多数 Pythonic 而言,我会说Python 源文档中提供的配方(其中一些看起来很像@JochenRitzel 提供的答案)可能是您最好的选择;)

def grouper(iterable, n, fillvalue=None):
    "Collect data into fixed-length chunks or blocks"
    # grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx
    args = [iter(iterable)] * n
    return izip_longest(fillvalue=fillvalue, *args)

在现代 Python 中,您只需zip_longest(*args, fillvalue=fillvalue) 根据相应的文档页面使用。

解决方案 5:

>>> my_list = [1,2,3,4,5,6,7,8,9,10]
>>> my_pairs = list()
>>> while(my_list):
...     a = my_list.pop(0); b = my_list.pop(0)
...     my_pairs.append((a,b))
... 
>>> print(my_pairs)
[(1, 2), (3, 4), (5, 6), (7, 8), (9, 10)]

解决方案 6:

是否有另一种“更好”的方法来成对遍历列表?

我不能肯定地说,但我对此表示怀疑:任何其他遍历都会包含更多必须解释的 Python 代码。像 zip() 这样的内置函数是用 C 编写的,速度要快得多。

哪种方法才是正确的,可以确保包含所有元素?

检查列表的长度,如果是奇数(len(list) & 1 == 1),则复制列表并附加一个项目。

解决方案 7:

只做:

>>> l = [1, 2, 3, 4, 5, 6]
>>> [(x,y) for x,y in zip(l[:-1], l[1:])]
[(1, 2), (2, 3), (3, 4), (4, 5), (5, 6)]

解决方案 8:

以下是使用生成器创建配对/腿的示例。生成器不受堆叠限制

def pairwise(data):
    zip(data[::2], data[1::2])

例子:

print(list(pairwise(range(10))))

输出:

[(0, 1), (2, 3), (4, 5), (6, 7), (8, 9)]

解决方案 9:

如果有人需要算法方面的答案,这里是:

>>> def getPairs(list):
...     out = []
...     for i in range(len(list)-1):
...         a = list.pop(0)
...         for j in a:
...             out.append([a, j])
...     return b
>>> 
>>> k = [1, 2, 3, 4]
>>> l = getPairs(k)
>>> l
[[1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4]]

但请注意,您的原始列表也将减少到其最后一个元素,因为您已经使用了pop它。

>>> k
[4]

解决方案 10:

这段代码对我有用。它创建元组对,如果列表长度为奇数(fillvalue=""),则将空字符串添加到最后一对。

zip_longest(*[iter(my_list)] * 2, fillvalue="")

# odd
list(zip_longest(*[iter([0, 1, 2, 3, 4, 5, 6])] * 2, fillvalue=""))
[(0, 1), (2, 3), (4, 5), (6, '')]

# even
list(zip_longest(*[iter([0, 1, 2, 3, 4, 5])] * 2, fillvalue=""))
[(0, 1), (2, 3), (4, 5)]
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   2796  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1710  
  PLM系统在企业项目管理中扮演着至关重要的角色,尤其是在项目采购管理方面,能够通过一系列策略提升采购效率、降低成本并保障质量。通过深入解析相关策略,企业可以更好地利用PLM系统优化采购流程,实现项目的顺利推进与整体目标的达成。需求精准定义策略在项目采购中,明确需求是首要任务。PLM系统可助力企业精准定义采购需求。首先,...
plm是什么意思   8  
  在企业的运营过程中,跨部门数据共享一直是一个关键且颇具挑战的问题。不同部门之间由于业务差异、系统不兼容等多种因素,常常形成信息孤岛,导致数据无法顺畅流通,影响企业整体的决策效率和协同效果。而 PLM 系统作为一种先进的管理工具,为解决这一难题提供了有效的途径。通过其一系列强大的核心功能,能够打破部门之间的数据壁垒,实现...
plm系统   7  
  PLM(产品生命周期管理)项目涉及产品从概念设计到退役的全流程管理,其复杂性和长期性要求高效的项目进度管理工具。甘特图作为一种直观且实用的项目进度可视化工具,在PLM项目中发挥着关键作用。通过甘特图,项目团队成员能够清晰地了解项目任务的时间安排、进度状态以及各项任务之间的关系,从而更好地协调工作、分配资源,确保项目按计...
plm流程是什么   6  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

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

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

内置subversion和git源码管理

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

免费试用