为了账号安全,请及时绑定邮箱和手机立即绑定

一对单对。

一对单对。

偶然的你 2019-12-26 10:09:06
通常,我发现需要成对处理列表。我想知道哪种方法是有效的pythonic方法,并在Google上找到了它:pairs = zip(t[::2], t[1::2])我认为这已经足够好用了,但是在最近涉及成语与效率的讨论之后,我决定进行一些测试:import timefrom itertools import islice, izipdef 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.145185947420.105381965637 1.35109519958 1.245713233950.00257992744446 1.46182489395 1.459244966510.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.255864858630.00222492218018 1.23795199394 1.23572707176到目前为止的结果最pythonic,非常有效:pairs = izip(t[::2], t[1::2])最有效且非常pythonic:pairs = izip(*[iter(t)]*2)我花了一点时间想知道第一个答案使用两个迭代器,而第二个答案使用一个迭代器。为了处理具有奇数个元素的序列,建议增加原始序列,增加一个元素(None)与之前的最后一个元素配对,这可以通过实现itertools.izip_longest()。最后请注意,在Python 3.x中,zip()其行为与一样itertools.izip(),并且itertools.izip() 消失了。
查看完整描述

3 回答

?
喵喔喔

TA贡献1735条经验 获得超5个赞

我最喜欢的方式:


from itertools import izip


def pairwise(t):

    it = iter(t)

    return izip(it,it)


# for "pairs" of any length

def chunkwise(t, size=2):

    it = iter(t)

    return izip(*[it]*size)

当您想配对所有元素时,您显然可能需要一个fillvalue:


from itertools import izip_longest

def blockwise(t, size=2, fillvalue=None):

    it = iter(t)

    return izip_longest(*[it]*size, fillvalue=fillvalue)


查看完整回答
反对 回复 2019-12-26
?
守着一只汪

TA贡献1872条经验 获得超3个赞

我想说您的初始解决方案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)]


查看完整回答
反对 回复 2019-12-26
?
神不在的星期二

TA贡献1963条经验 获得超6个赞

我从小的免责声明开始-不要使用下面的代码。根本不是Pythonic,我只是为了好玩而写。它类似于@ THC4k pairwise函数,但使用iter和lambda闭包。它不使用itertools模块,不支持fillvalue。我把它放在这里是因为有人可能会觉得有趣:


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


查看完整回答
反对 回复 2019-12-26
  • 3 回答
  • 0 关注
  • 334 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信