将itertools.chain对象转换/解包为无序和有序列表的最有效方法

时间:2017-02-12 13:01:01

标签: python python-3.x itertools

除了使用listsorted方法转换itertools.chain对象以分别得到无序和有序列表之外,还有更有效的方法在python3中做同样的事情吗?我在这个answer中读到该列表用于调试。这是真的吗?

下面是我为进程计时的示例代码:

from itertools import chain
from time import time

def foo(n):
        for i in range(n):
            yield range(n)

def check(n):
    # check list method
    start = time()
    a = list(itertools.chain.from_iterable(foo(n)))
    end = time()- start
    print('Time for list = ', end)
    # check sorted method
    start = time()
    b = sorted(itertools.chain.from_iterable(foo(n)))
    end = time()- start
    print('Time for sorted = ', end)

结果:

>>> check(1000)
Time for list =  0.04650092124938965
Time for sorted =  0.08582258224487305
>>> check(10000)
Time for list =  1.615750789642334
Time for sorted =  8.84056806564331
>>>

2 个答案:

答案 0 :(得分:1)

最有效的方法是使用list(),但是如果你想通过itertools.chain()展平嵌套迭代或连接一些迭代,然后将它转换为列表,你可以立即使用嵌套列表理解。 sorted()花费更多时间的原因是它对iterable进行排序,而list只调用生成器函数的某些方法(如__next__),以便将项目复制到列表对象。

请注意,就运行时而言,itertools.chain的执行速度可能比列表推导(python 2.x和python 3.x)略快。这是一个例子:

In [27]: lst = [range(10000) for _ in range(10000)]

In [28]: %timeit [i for sub in lst for i in sub]
1 loops, best of 3: 3.94 s per loop

In [29]: %timeit list(chain.from_iterable(lst))
1 loops, best of 3: 2.75 s per loop

答案 1 :(得分:1)

  

除了使用list和sorted方法将itertools.chain对象转换成无序和有序列表之外,还有更有效的方法在python3中做同样的事情吗?

答案很简单:没有。使用python生成器和迭代器时,唯一需要注意的是将生成器转换为列表,然后转换为生成器,然后再转换为列表等等......

即。像这样的连锁店是愚蠢的:

list(sorted(list(filter(list(map(…

因为你会失去发电机的所有附加价值。

  

我在这个答案中读到该列表用于调试。这是真的?

这取决于你的上下文,一般来说list()不是用于调试,它是表示可迭代的不同方式。

如果您需要访问给定索引处的元素,或者您想知道数据集的长度,则可能需要使用list()。 如果您可以随时使用数据,则不希望使用list()

将所有生成器/迭代器方案视为在每个项目可用时应用算法的方法,而将列表作为批量处理。

关于你引用的问题,问题是非常具体的,它询问如何从REPL内省发电机,以了解内部的内容。回答这个问题的人的建议是仅使用list(chain)进行内省,但保留最初的内容。