【问题标题】:Writing a list comprehension to flatten a nested list [duplicate]编写列表理解以展平嵌套列表[重复]
【发布时间】:2017-11-09 02:09:27
【问题描述】:

我有一个包含列表和数字的嵌套列表。

nested = [[1, 2, 3], [4, 5, 6], [7, 8], [9], 10, 11]

嵌套列表只包含数字,它们永远不会包含更多列表。

是否可以编写一个列表推导来从“嵌套”列表中创建新列表,产生以下输出?

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

这是我的尝试(代码不工作)

[num if isinstance(item, list) for num in item else item for item in nested]

【问题讨论】:

  • 您没有固定的清单,使事情变得复杂。你的列表会有多不规则?
  • 这是我的确切列表 [[1,2,3] , [4,5,6] , [7,8] , [9,] , 10 , 11 ]
  • 这不是我问的。您的嵌套列表是否会包含 更多 个列表?
  • 不,内部列表是普通列表,不是嵌套列表。
  • 密切相关,但任意嵌套会留下一个列表理解选项:Flatten (an irregular) list of lists

标签: python list python-3.x list-comprehension


【解决方案1】:

您需要将您的实例测试放在一个循环中,这样您就可以从嵌套列表中提取元素:

[num for item in nested for num in (item if isinstance(item, list) else (item,))]

演示:

>>> nested = nested = [[1, 2, 3], [4, 5, 6], [7, 8], [9], 10, 11]
>>> [num for item in nested for num in (item if isinstance(item, list) else (item,))]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]

如果您首先将其表达为一组for 循环,将会有所帮助;您的尝试基本上是这样做的:

for item in nested:
    _element = num if isinstance(item, list) for num in item else item
    result.append(_element)

这不是真正有效的 Python。

我上面的列表理解是这样做的:

for item in nested:
    _iterable = item if isinstance(item, list) else (item,)
    for num in _iterable:
        _element = num
        result.append(_element)

【讨论】:

  • 很好的答案,它不考虑包含元组或可迭代容器和不可迭代对象的列表作为使用说明......
  • @dawg:不,因为这超出了问题的要求,这就是为什么我要求对帖子进行澄清并最终将其复制到与我在 cmets 中链接的帖子不同的帖子中。
【解决方案2】:

如果您的列表有任意嵌套,最好使用递归函数 (referring to one of my other answers):

>>> def flat_gen(x):
...     def iselement(e):
...         return not(isinstance(e, collections.Iterable) and not isinstance(e, str))
...     for el in x:
...         if iselement(el):
...             yield el
...         else:
...             yield from flat_gen(el)   
... 
>>> nested = [[1,2,3] , [4,5,6] , [7,8] , [9,] , 10 , 11 ]

>>> import collections
>>> list(flat_gen(nested))
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]

如果您只是在简单列表或元组(任何可迭代容器)和非列表或元组对象(即不可迭代对象和没有更深嵌套的可迭代容器)之间混合嵌套,您可以使用带有 @987654324 的生成器表达式@:

>>> import itertools as it
>>> list(it.chain.from_iterable(item if isinstance(item,collections.Iterable) and not isinstance(item, str) else [item] for item in nested))
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]

【讨论】:

  • OP 要求对列表进行理解,否则我们可能同样会根据您提出的问题而受骗。
  • @MartijnPieters 这显然是个骗局,不是吗? stackoverflow.com/questions/17338913/…
  • @StefanPochmann:有趣,没见过那个。而且那里没有正确的列表理解答案。
  • @StefanPochmann:我相信一个允许更多嵌套。
  • @MartijnPieters 我不这么认为。该问题包含无法处理更深嵌套的打印代码,并且该问题听起来像是在工作。
猜你喜欢
  • 1970-01-01
  • 2018-01-30
  • 1970-01-01
  • 1970-01-01
  • 2013-12-05
  • 2013-11-17
  • 2018-07-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多