通过列表理解来展平列表列表

问题描述 投票:0回答:6

我正在尝试使用 python 中的列表理解来展平列表。我的清单有点像

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

只是为了打印这个列表中的单个项目我写了这个函数:

def flat(listoflist):
    for item in listoflist:
        if type(item) != list:
            print(item)
        else:
            for num in item:
                print(num)

互动输出:

>>> flat(list1)
1
2
3
4
5
6
7
8

然后我使用相同的逻辑通过列表理解来展平我的列表我收到以下错误

list2 = [item if type(item) != list else num for num in item for item in list1]

这给了我以下错误:

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'int' object is not iterable

如何使用列表推导来展平这种类型的列表?

python list python-2.7 list-comprehension
6个回答
27
投票

没有人给出通常的答案:

def flat(l):
  return [y for x in l for y in x]

StackOverflow 周围流传着这个问题的骗局。


13
投票
>>> from collections import Iterable
>>> from itertools import chain

单线:

>>> list(chain.from_iterable(item if isinstance(item,Iterable) and
                    not isinstance(item, basestring) else [item] for item in lis))
[1, 2, 3, 4, 5, 6, 7, 8]

可读版本:

>>> def func(x):                                         #use `str` in py3.x 
...     if isinstance(x, Iterable) and not isinstance(x, basestring): 
...         return x
...     return [x]
... 
>>> list(chain.from_iterable(func(x) for x in lis))
[1, 2, 3, 4, 5, 6, 7, 8]
#works for strings as well
>>> lis = [[1, 2, 3], [4, 5, 6], 7, 8, "foobar"]
>>> list(chain.from_iterable(func(x) for x in lis))                                                                
[1, 2, 3, 4, 5, 6, 7, 8, 'foobar']

使用嵌套列表理解:(与

itertools.chain
相比会很慢):

>>> [ele for item in (func(x) for x in lis) for ele in item]
[1, 2, 3, 4, 5, 6, 7, 8, 'foobar']

3
投票

使用发电机的替代解决方案:

import collections

def flatten(iterable):
    for item in iterable:
        if isinstance(item, collections.Iterable) and not isinstance(item, str):  # `basestring` < 3.x
            yield from item  # `for subitem in item: yield item` < 3.3
        else:
            yield item

>>> list(flatten([[1, 2, 3], [4, 5, 6], 7, 8]))
[1, 2, 3, 4, 5, 6, 7, 8]

3
投票

你正试图遍历一个数字,你不能这样做(因此错误)。

如果您使用的是 python 2.7:

>>> from compiler.ast import flatten
>>> flatten(l)
[1, 2, 3, 4, 5, 6, 7, 8]

但请注意,该模块现已弃用,Python 3 中不再存在


2
投票
def nnl(nl):    # non nested list

    nn = []

    for x in nl:
        if type(x) == type(5):
            nn.append(x)

    if type(x) == type([]):
        n = nnl(x)

        for y in n:
            nn.append(y)
    return nn

print (nnl([[9, 4, 5], [3, 8,[5]], 6]))  # output: [9, 4, 5, 3, 8, 5, 6]

0
投票

这里有一个使用精度和生成器的更高效和快速的解决方案,它也适用于高度嵌套的列表。

实施

def _flatten_list(l: list):
    for item in l:
        if isinstance(item, list):
            yield from flatten_list(item)
        else:
            yield item
            
def flatten_list(l: list):
    return list(_flatten_list(l))
        
example = [1, 2, [3, 4, [5, 6], 7], 8, [9, [10]]]
print(flatten_list(example))

输出

> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
© www.soinside.com 2019 - 2024. All rights reserved.