一对单对 [英] Pairs from single list

查看:89
本文介绍了一对单对的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Often enough, I've found the need to process a list by pairs. I was wondering which would be the pythonic and efficient way to do it, and found this on Google:

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

我认为这已经足够Python了,但是在最近涉及效率,我决定做一些测试:

I thought that was pythonic enough, but after a recent discussion involving idioms versus efficiency, I decided to do some tests:

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

这些是我计算机上的结果:

These were the results on my computer:

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中列表,列表索引和列表切片的实现非常有效.这是令人安慰和出乎意料的结果.

If I'm interpreting them correctly, that should mean that the implementation of lists, list indexing, and list slicing in Python is very efficient. It's a result both comforting and unexpected.

还有另一种更好"的成对遍历列表的方法吗?

请注意,如果列表中元素的数量为奇数,则最后一个元素将不在任何对中.

Note that if the list has an odd number of elements then the last one will not be in any of the pairs.

哪种方法才是确保所有元素都包括在内的正确方法?

我从测试答案中添加了这两个建议:

I added these two suggestions from the answers to the tests:

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且非常有效:

Results so far

Most pythonic and very efficient:

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

最高效且非常Python化:

Most efficient and very pythonic:

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

我花了一点时间来思考,第一个答案使用了两个迭代器,而第二个答案使用了一个迭代器.

It took me a moment to grok that the first answer uses two iterators while the second uses a single one.

要处理具有奇数个元素的序列,建议是增加原始序列,增加一个元素(None),该元素与之前的最后一个元素配对,这可以通过itertools.izip_longest()来实现.

To deal with sequences with an odd number of elements, the suggestion has been to augment the original sequence adding one element (None) that gets paired with the previous last element, something that can be achieved with itertools.izip_longest().

请注意,在Python 3.x中,zip()的行为与itertools.izip()相同,而itertools.izip()消失了.

Note that, in Python 3.x, zip() behaves as itertools.izip(), and itertools.izip() is gone.

推荐答案

我最喜欢的方法:

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)

要配对所有元素时,显然可能需要填充值:

When you want to pair all elements you obviously might need a fillvalue:

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

这篇关于一对单对的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆