【问题标题】:Convert nested tuples to nested lists将嵌套元组转换为嵌套列表
【发布时间】:2017-09-16 04:58:53
【问题描述】:
I/P - (('1', (('2355', '5'), 'F')),
       ('1', (('2300', '4'), 'M')),
       ('1', (('2400', '5'), 'F')))
O/P - [['1','2355','5','F'],
       ['1','2300','4','M'],
       ['1','2400','5','F']]

我能够获取第一个元素,但其他元素仍被提取为元组,而我希望所有元素都作为列表的一部分出现。基本上,我希望每个元素都作为列表的一部分单独出现。

【问题讨论】:

    标签: python python-2.7 list tuples


    【解决方案1】:

    在 3.3+ 中,有一个递归习惯用法可以修改为扁平化任何深度的嵌套元组(请参阅:系统递归限制)

    def yielder(x):
        for y in x:
            if isinstance(y, tuple):
                yield from yielder(y)
            else:
                yield y
    

    然后可以在列表推导中使用

    [[*yielder(e)] for e in IP]
    Out[48]: [['1', '2355', '5', 'F'], ['1', '2300', '4', 'M'], ['1', '2400', '5', 'F']]
    

    我通过在 https://jugad2.blogspot.in/2014/10/flattening-arbitrarily-nested-list-in.html 的 cmets 中搜索“python flatten”找到了上述内容

    对于 2/7 http://joedicastro.com/aplanar-listas-en-python.html 有食谱,我修改了:

    def flat_slice ( lst ):
        lst = list ( lst )
        for i , _ in enumerate ( lst ):
            while ( hasattr ( lst [ i ], "__iter__" ) and not isinstance ( lst [ i ], basestring )):
                 lst [ i : i + 1 ] = lst [ i ]
        return lst
    

    (我必须将 basestring 更改为 str 3+)

    结果还是一样

    [[*flat_slice(e)] for e in IP]
    Out[66]: [['1', '2355', '5', 'F'], ['1', '2300', '4', 'M'], ['1', '2400', '5', 'F']]
    

    【讨论】:

    • 还有其他方法吗?我正在使用 Python 2.7,无法升级。
    • 如果 ti 很重要,您应该将版本放在标签中。因为否则,这是一个非常巧妙的答案。
    【解决方案2】:
    def flaten(t,level=0):
       l = []
       for t1 in t:
         if type(t1) is tuple:
           if level == 0:
             l.append(flaten(t1,level+1))
           else:
             l.extend(flaten(t1,level+1))
         else:
           l.append(t1)
       return l
    
    t = (('1', (('2355', '5'), 'F')), ('1', (('2300', '4'), 'M')), ('1', (('2400', '5'), 'F')))
    l = flaten(t)
    print(l)
    

    【讨论】:

      【解决方案3】:

      我将其保留为一个简单的递归例程,该例程也可用于理解:

      def unpack(element, stack):
          if isinstance(element, basestring):
              stack.append(element)
          else:
              for i in element:
                  unpack(i, stack)
          return stack
      
      [unpack(row, []) for row in IP]
      

      输出:

      [['1', '2355', '5', 'F'], ['1', '2300', '4', 'M'], ['1', '2400', '5', 'F']]
      

      【讨论】:

      • 什么是基串?
      • Google 是你的朋友:“ basestring()¶ 这个抽象类型是 str 和 unicode 的超类。它不能被调用或实例化,但它可以用来测试一个对象是str的实例还是unicode的实例。 isinstance(obj, basestring) 等价于 isinstance(obj, (str, unicode))。”
      【解决方案4】:

      迭代每个可迭代对象,展平所有元素,然后将可迭代对象重新转换为列表。这里有两种方法:

      给定

      iterables = (
          ('1', (('2355', '5'), 'F')),
          ('1', (('2300', '4'), 'M')),
          ('1', (('2400', '5'), 'F'))
      )
      
      expected = [
          ['1','2355','5','F'],
          ['1','2300','4','M'],
          ['1','2400','5','F']
      ]
      

      代码

      this post 修改的flatten(兼容Python 2/3):

      # Approach 1
      from collections import Iterable
      
      
      def flatten(items):
          """Yield items from any nested iterable"""
          for x in items:
              if isinstance(x, Iterable) and not isinstance(x, (str, bytes)):
                  for i in flatten(x):
                      yield i
              else:
                  yield x
      
      actual = [list(flatten(i)) for i in iterables]
      assert actual == expected
      

      对于单行,请考虑 more_itertools.collapse,这是一种还可以扁平化嵌套迭代的工具:

      # Approach 2
      import more_itertools as mit
      
      
      actual = [list(mit.collapse(i)) for i in iterables]
      assert actual == expected
      

      注意:more_itertools 是一个第三方库,它实现了几个itertools recipes 和有用的工具。通过pip install more_itertools安装。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-02-28
        • 2013-12-07
        • 1970-01-01
        • 2017-09-11
        • 2019-12-28
        相关资源
        最近更新 更多