来自单个列表的对

问题描述 投票:92回答:7

[通常,我发现需要成对处理列表。我想知道哪种方法是有效的pythonic方法,并在Google上找到了它:

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

我认为这已经足够了pythonic,但是在最近涉及idioms versus efficiency的讨论之后,我决定进行一些测试:

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

到目前为止的结果

最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()消失了。

[通常,我发现需要成对处理列表。我想知道哪种方法是有效的pythonic方法,并在Google上找到了它:pair = zip(t [:: 2],t [1 :: 2])我以为...

python list zip slice idioms
7个回答
48
投票
我最喜欢的方式:

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

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

3
投票
就大多数pythonic而言,我会说recipes supplied in the python source docs(其中一些看起来很像@JochenRitzel提供的答案)可能是您最好的选择;]

2
投票
还有另一种“更好”的成对遍历列表的方法吗?

2
投票
>>> 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)]

0
投票
这里是使用生成器创建对/腿的示例。生成器不受堆栈限制
© www.soinside.com 2019 - 2024. All rights reserved.