【问题标题】:flatten list of list through list comprehension通过列表理解展平列表列表
【发布时间】:2013-06-24 16:54:24
【问题描述】:

我正在尝试在 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


    【解决方案1】:

    没有人给出通常的答案:

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

    这个问题在 StackOverflow 上到处都是骗子。

    【讨论】:

    • 您的代码不适用于 OP 提供的列表,因为他的列表包含不可迭代的对象,即整数。但是,如果列表中的每个项目都是可迭代对象,则您的代码确实有效。请参阅下面的评论。
    • 感谢您指出这一点 - 我实际上需要找点时间来解决这个问题并开始处理......
    【解决方案2】:
    >>> 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']
    

    【讨论】:

    • 这对于使用 2.x 的提问者来说非常有用,但值得注意的是,3.x 用户应该使用 str 而不是 basestring
    • @Ashwini 如果我的元素是 dict 而不是整数类型应该怎么办?
    • @AnuragSharma 小例子?
    • @AshwiniChaudhary 例如 ---> [[{'ascdd': 'skj'}, {'fd': 'srsr'}], {'dsf': 'ds', 'ds ': 'dsffd'}]
    • @AnuragSharma 这个案例的预期输出是什么?
    【解决方案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]
    

    【讨论】:

      【解决方案4】:

      您正在尝试遍历一个数字,但您不能这样做(因此出现错误)。

      如果您使用的是 python 2.7:

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

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

      【讨论】:

      • 类型检查列表是个坏主意。它使这变得不那么灵活。
      • 如果l[[1, 2, 3], [4, 5, 6], 7, 888],第一个解产生[1, 2, 3, 4, 5, 6, 7, 8, 8, 8]
      • 删除了第一位,但很遗憾我的其他解决方案在 python 3 中不起作用
      【解决方案5】:
      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]
      

      【讨论】:

      • 或许解释一下也会有所帮助。
      • 此解决方案使用递归。 对于嵌套列表中的每个元素,您检查该元素是整数还是列表。如果是整数,我们将该整数附加到列表 nn 中。如果嵌套列表中的元素是列表,则调用递归函数,您将对子列表执行您对初始嵌套列表所做的操作。然后在nn中再次追加不是列表的元素。 nn 的输出将是一个非嵌套列表。祝大家编码愉快!
      • 太棒了!现在请edit your answer添加此信息。
      • 完成 - Namasté。
      猜你喜欢
      • 2023-04-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-19
      • 2018-01-30
      相关资源
      最近更新 更多