【问题标题】:How can I flatten lists without splitting strings?如何在不拆分字符串的情况下展平列表?
【发布时间】:2011-07-14 06:42:47
【问题描述】:

我想扁平化可能包含其他列表的列表而不将字符串分开。例如:

In [39]: list( itertools.chain(*["cat", ["dog","bird"]]) )
Out[39]: ['c', 'a', 't', 'dog', 'bird']

我愿意

['cat', 'dog', 'bird']

【问题讨论】:

    标签: python


    【解决方案1】:

    解决方案:

    def flatten(foo):
        for x in foo:
            if hasattr(x, '__iter__') and not isinstance(x, str):
                for y in flatten(x):
                    yield y
            else:
                yield x
    

    Python 2.x 的旧版本:

    def flatten(foo):
        for x in foo:
            if hasattr(x, '__iter__'):
                for y in flatten(x):
                    yield y
            else:
                yield x
    

    (在 Python 2.x 中,字符串实际上没有 __iter__ 属性,这与 Python 中几乎所有其他可迭代对象不同。但是请注意,它们在 Python 3 中具有,因此上述代码仅适用于Python 2.x.)

    【讨论】:

    • 只有 Python 3 版本使用 isinstance() 并且 Python 3 中没有 basestring 类,因为所有字符串都是 Unicode。
    • @Hugh Bothwell:Python 2.x 中的hasattr(u'foo', '__iter__') == False,而Python 3 没有basestring,只有str(unicode)和bytes。
    • 看起来 Python 3 版本也可以在 Python 2 中使用,即使它有点多余。
    【解决方案2】:

    蛮力的方法是将字符串包装在自己的列表中,然后使用itertools.chain

    >>> l = ["cat", ["dog","bird"]]
    >>> l2 = [([x] if isinstance(x,str) else x) for x in l]
    >>> list(itertools.chain(*l2))
    ['cat', 'dog', 'bird']
    

    【讨论】:

      【解决方案3】:

      对 orip 的回答稍作修改,以避免创建中间列表:

      import itertools
      items = ['cat',['dog','bird']]
      itertools.chain.from_iterable(itertools.repeat(x,1) if isinstance(x,str) else x for x in items)
      

      【讨论】:

        【解决方案4】:
        def squash(L):
            if L==[]:
                return []
            elif type(L[0]) == type(""):
                M = squash(L[1:])
                M.insert(0, L[0])
                return M
            elif type(L[0]) == type([]):
                M = squash(L[0])
                M.append(squash(L[1:]))
                return M
        
        def flatten(L):
            return [i for i in squash(L) if i!= []]
        
        >> flatten(["cat", ["dog","bird"]])
        ['cat', 'dog', 'bird']
        

        希望对你有帮助

        【讨论】:

          【解决方案5】:

          这是一种单行方法:

          [item for sublist in [[item] if type(item) is not list else item for item in list1] for item in sublist]
          

          【讨论】:

            【解决方案6】:

            使用 functools 库中的 reduce 函数,您可以这样做:

            import functools
            items = ['cat',['dog','bird']]
            print(functools.reduce(lambda a, b: [a] + b, items))
            

            【讨论】:

            • 如果items 的第一个元素是列表则不起作用:functools.reduce(lambda a, b: [a] + b, [["dog", "bird"], "cat"]) 给出TypeError: can only concatenate list (not "str") to list
            【解决方案7】:

            一种适用于两个以上层次结构的 lambda 函数方法

            >>> items = ['cat',['dog','bird',['fish']]] 
            >>> flatten = lambda y: [k for j in ([i] if not isinstance(i,list) else flatten(i) for i in y) for k in j]
            >>> flatten(items)
            ['cat', 'dog', 'bird', 'fish']
            

            【讨论】:

              猜你喜欢
              • 2020-04-09
              • 1970-01-01
              • 1970-01-01
              • 2019-01-21
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2019-06-11
              • 1970-01-01
              相关资源
              最近更新 更多