来自单个列表的对 [英] Pairs from single list

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

问题描述

经常,我发现需要成对处理列表.我想知道哪种 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])

我认为这已经足够 Pythonic,但在最近讨论了 习语与效率,我决定做一些测试:

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

这是我电脑上的结果:

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])

最高效且非常pythonic:

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.

推荐答案

我最喜欢的做法:

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)

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

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)

在 Python 3 中,itertools.izip 现在只是 zip .. 要使用较旧的 Python,请使用

With Python 3, itertools.izip is now simply zip .. to work with an older Python, use

from itertools import izip as zip

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

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