繁体   English   中英

itertools.islice与列表切片进行比较

[英]itertools.islice compared to list slice

我一直在尝试应用一种算法,根据某个标准将python列表缩小为较小的列表。 由于原始列表的大量,大约100k元素,我试图itertools避免多个内存分配,所以我想出了这个:

reducedVec = [ 'F' if sum( 1 for x in islice(vec, i, i+ratio) if x == 'F' ) 
                         > ratio / 3.0 else 'T'
                for i in xrange(0, len(vec), ratio) ]

当vec有大约100k元素时,执行时间大约需要几分钟。 当我尝试时:

reducedVec = [ 'F' if sum( 1 for x in vec[i:i+ratio] if x == 'F' ) 
                         > ratio / 3.0 else 'T'
                for i in xrange(0, len(vec), ratio) ]

本质上用切片替换islice,执行是瞬时的。

你能想到一个合理的解释吗? 我本以为避免重复分配一个包含大量元素的新列表,实际上可以节省一些计算周期而不是削弱整个执行。

干杯,忒弥斯

islice适用于任意迭代。 要做到这一点,不是直接跳到第n个元素,而是必须迭代第一个n-1,抛弃它们,然后产生你想要的那个。

查看itertools文档中的纯Python实现:

def islice(iterable, *args):
    # islice('ABCDEFG', 2) --> A B
    # islice('ABCDEFG', 2, 4) --> C D
    # islice('ABCDEFG', 2, None) --> C D E F G
    # islice('ABCDEFG', 0, None, 2) --> A C E G
    s = slice(*args)
    it = iter(xrange(s.start or 0, s.stop or sys.maxint, s.step or 1))
    nexti = next(it)
    for i, element in enumerate(iterable):
        if i == nexti:
            yield element
            nexti = next(it)

说到itertools文档,如果我尝试执行此操作,我可能会使用grouper配方。 它实际上不会为你节省任何记忆,但如果你把它重写为更懒惰的话,它可能会变得更加困难。

from __future__ import division

from itertools import izip_longest
def grouper(n, iterable, fillvalue=None):
    "grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx"
    args = [iter(iterable)] * n
    return izip_longest(fillvalue=fillvalue, *args)

reducedVec = []
for chunk in grouper(ratio, vec):
    if sum(1 for x in chunk if x == 'F') > ratio / 3:
        reducedVec.append('F')
    else:
        reducedVec.append('T')

我喜欢使用grouper来抽象出连续的切片,并且发现这个代码比原始代码更容易阅读

我的猜测是使用islice()涉及对vec每个元素进行Python函数调用,而扩展切片表示法由解析器理解并直接转换为CPython调用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM