具有可变数量元素

时间:2018-02-12 02:58:59

标签: python python-3.x iterable-unpacking pep pep448

接受 PEP 448 已在Python 3.5中引入了 其他解包广义

例如:

>>> l1 = [1, 2, 3]
>>> l2 = [4, 5, 6]

# unpack both iterables in a list literal
>>> joinedList = [*l1, *l2]
>>> print(joinedList)
[1, 2, 3, 4, 5, 6]

问题:有没有办法用列表列表做类似的事情?

此代码不起作用:

  

SyntaxError:迭代解包不能用于理解

# List of variable size
list_of_lists = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
joined_list = [*l for l in list_of_lists]

当然,您可以执行以下操作,但看起来不那么优雅且效率不高:

# List of variable size
list_of_lists = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
joined_list = list()
for l in list_of_lists:
    joined_list += l

2 个答案:

答案 0 :(得分:1)

去读旧学怎么样:sum()

代码:

joined_list = sum(list_of_lists, [])

测试代码:

# List of variable size
list_of_lists = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
joined_list = sum(list_of_lists, [])
print(joined_list)

结果:

[1, 2, 3, 4, 5, 6, 7, 8, 9]

答案 1 :(得分:0)

我不鼓励在这里使用sum,因为它是Schlemiel the Painter's algorithm的一种形式。 sum实际上禁止使用str;他们并没有尝试阻止所有序列使用,以免降低sum的尝试速度,以阻止每次滥用,但这仍然不是一个好主意。

问题在于,这意味着您每次都会构建逐渐变大的临时list,在复制下一个 之后,您将在构建下一个临时list时将其丢弃,再加上新的东西。如果第一个列表中有一百万个项目,并且您还有十个以上的list串联在一起,那么您正在复制至少一千万个元素(即使其他十个+=是空的) )。您的原始代码实际上更好,因为使用O(n)运算符执行了就地扩展,在n中保持了最差情况的性能(对于所有list的{​​{1}}元素s)范围,而不是O(n*m)(对于n m s中的list个元素)。

它还具有仅适用于一种一致类型的问题;如果某些输入是list,某些tuple和某些生成器,则sum将不起作用(因为list.__add__将不接受非list另一边的操作数)。

所以不要那样做。这是what itertools.chain and it's alternate constructor, itertools.chain.from_iterable were made for

from itertools import chain

list_of_lists = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
joined_list = list(chain.from_iterable(list_of_lists))

保证得到O(n),它可以与您扔给它的所有可迭代项一起使用,等等。

是的,很显然,如果您只得到三个元素中的三个list,就没关系了。但是,如果输入可迭代项的大小或可迭代项的数量任意大,或者类型不一致,则chain将起作用,sum将不会起作用。