如何提取嵌套列表?

26

虽然这可能是某个问题的重复,但它不是所链接问题的重复,该问题是关于创建像[["a", "d", "g"], ["a", "d", "h"], ["a", "d", "i"], ...]这样的列表,这完全不是这里想要的。 - agf
1
@agf 用实际重复项替换了可能的重复项。 - dbr
3个回答

44

使用itertools.chain

from itertools import chain

list(chain.from_iterable(list_of_lists))

6
你可以再解释一些。 - GLHF
6
这是一个简单的问题(也已经四年之久),并且不需要比我提供的文档和示例更多的解释。请问您需要什么样的帮助呢? - agf

27

itertools文档中有一个明显的例子(参见http://docs.python.org/library/itertools.html#recipes查找flatten()),但它很简单:

>>> from itertools import chain
>>> list(chain(*x))
['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']

或者,可以在一个列表理解式中轻松完成:

>>> x=[["a","b","c"], ["d","e","f"], ["g","h","i","j"]]
>>> [j for i in x for j in i]
['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']

或者通过reduce()函数:

>>> from operator import add
>>> reduce(add, x)
['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']

2
"chain.from_iterable(x)" 是现代 Python 的惯用语,表示 "chain(*x)"。 - agf
列表生成式更符合Python风格! - Angel Salazar
list.__add__也可用,无需从operator导入add。 - mh-firouzjah

3

使用 itertools.chain 的替代方案是:

>>> li = [["a","b","c"], ["d","e","f"], ["g","h","i","j"]]
>>> chained = []
>>> while li:
...     chained.extend(li.pop(0))
... 
>>> chained
['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']

编辑:上面的例子会在构建新列表时消耗原始列表,因此如果您正在操作非常大的列表并希望最小化内存使用,则应该是一个优势。如果不是这种情况,我会考虑使用itertools.chain更加“Pythonic”的方法来实现结果。


谢谢。我尝试使用list(itertools.chain(*a))来解决这个问题,但是却总是出现 TypeError: object of type 'NoneType' has no len() 的错误信息。当我在一个简单的列表上尝试时,它能正常工作,但是当我在一个更长或者更复杂的列表上尝试时,就会出现这个错误。也许这和存在多个空的嵌套列表([])有关呢?谢谢。 - user1040563
@user1040563 你具体尝试了什么?对我来说,无论是我的解决方案还是agf的解决方案,即使有空子列表也都能正常工作... - mac
这比chain或类似的解决方案具有更高的时间复杂度,因为pop(0)是O(n) -- 请参见Python Wiki Time Complexity页面中“list section”的“delete item”条目。如果您想使用extend并使整个过程成为线性时间,则只需for sublist in li: chained.extend(li) -- 在Python中没有办法从list中以线性时间完成它,而不需要额外的存储空间(我假设这就是您想避免的)。 - agf
@agf - 的确,我认为在构建新列表时消耗原始列表是这种解决方案的“附加值”...感谢您提供时间复杂度页面的链接。我忽略了它的存在。有趣! :) - mac
我不同意这个版本适合非常大的列表。如果子列表很短但由于子列表数量众多,复杂度为 O(总长度 * 子列表数),那么它肯定很糟糕。如果子列表很长但数量不太多,那么它可能很好,因为可以节省内存,但请记住,第二个列表的内存使用仅为子列表中对象的引用,不会复制对象,因此内存必须非常紧张才行。 - agf
@user1040563 使用 res = reduce(list.__add__, listofitems) 是安全的,不会出现你遇到的错误。 - mh-firouzjah

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