可以使用 sum() 函数合并列表吗?

3

在使用Python进行列表拼接时,使用sum()函数是否符合Pythonic的风格?

>>> sum(([n]*n for n in range(1,5)),[])
[1, 2, 2, 3, 3, 3, 4, 4, 4, 4]

可能不太符合 Python 的风格,但我就是这么写的 ;) - zvone
看看这里的评论(https://dev59.com/qnNA5IYBdhLWcg3wdtld#952946)。它有O(N^2)的复杂度。 - ayhan
要将列表附加到一起,请查看 itertools.chainitertools.chain.from_iterable - chapelo
2个回答

7
不,实际上它是shlemiel绘画算法。因为每次想要连接一个新列表时,它都必须从开头遍历整个列表。(有关更多信息,请阅读Joel的这篇文章:http://www.joelonsoftware.com/articles/fog0000000319.html)
最Pythonic的方法是使用列表推导式:
In [28]: [t for n in range(1,5) for t in [n]*n ]
Out[28]: [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]

或者使用 itertools.chain:

In [29]: from itertools import chain

In [32]: list(chain.from_iterable([n]*n for n in range(1,5)))
Out[32]: [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]

或者作为一种纯生成器的方法,您可以使用repeat而不是乘以列表:

In [33]: from itertools import chain, repeat

# In python2.X use xrange instead of range
In [35]: list(chain.from_iterable(repeat(n, n) for n in range(1,5)))
Out[35]: [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]

如果你对NumPy感兴趣,或者想要一种超快的方法,这里有一个:

In [46]: import numpy as np
In [46]: np.repeat(np.arange(1, 5), np.arange(1, 5))
Out[46]: array([1, 2, 2, 3, 3, 3, 4, 4, 4, 4])

3

不,对于大型列表,这种方法会变得非常缓慢。列表推导式是更好的选择。

用列表推导式、总和和itertools.chain.from_iterable计时展平列表的代码:

import time
from itertools import chain

def increasing_count_lists(upper):
    yield from ([n]*n for n in range(1,upper))

def printtime(func):
    def clocked_func(*args):
        t0 = time.perf_counter()
        result = func(*args)
        elapsed_s = time.perf_counter() - t0
        print('{:.4}ms'.format(elapsed_s*1000))
        return result
    return clocked_func

@printtime
def concat_list_sum(upper):
    return sum(increasing_count_lists(upper), [])

@printtime
def concat_list_listcomp(upper):
    return [item for sublist in increasing_count_lists(upper) for item in sublist]

@printtime
def concat_list_chain(upper):
    return list(chain.from_iterable(increasing_count_lists(upper)))

并运行它们:

>>> _ = concat_list_sum(5)
0.03351ms
>>> _ = concat_list_listcomp(5)
0.03034ms
>>> _ = concat_list_chain(5)
0.02717ms
>>> _ = concat_list_sum(50)
0.2373ms
>>> _ = concat_list_listcomp(50)
0.2169ms
>>> _ = concat_list_chain(50)
0.1467ms
>>> _ = concat_list_sum(500)
167.6ms
>>> _ = concat_list_listcomp(500)
8.319ms
>>> _ = concat_list_chain(500)
12.02ms

感谢您提供这些数字。 - VPfB

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接