清理动态生成的嵌套元组

时间:2016-04-24 20:13:21

标签: python tuples generator stdtuple

我已经实现了一个算法,用于在python中执行任意嵌套dicts的笛卡尔积。根级别中的字段需要在多行中复制,因为也可以嵌入数组。我已经递归地使用了itertools.product聚合中间迭代器。

它正在运作,但问题是在决赛中打开包装。 我最终得到了这样的结构:

(11, 12.2, 123.2, 1.23, 104.75, (10.7, 104.75, 104.75, ('N', True, False, 'B2B'), 99.01, 6.3, 1.23, 5.87, 12.2), 1, 'SP', 7)

我正在寻找列表理解或生成器表达式,甚至是一个完整的生成器,它可以将此行展平并清理为:

(11, 12.2, 123.2, 1.23, 104.75, 10.7, 104.75, 104.75, 'N', True, False, 'B2B', 99.01, 6.3, 1.23, 5.87, 12.2, 1, 'SP', 7)

最好和最快的方法是什么?

修改

实际上,我所要求的是列表理解或生成器表达式甚至是一个完整的生成器,因为我需要将它包含在一个钩子中,拦截输出itertools.product本身。我不需要一个方式来清理这些tupples。所以不是重复。

伙计们,拜托,我不想要任何递归功能! 我有一个类__iter__()方法返回itertools.product动态生成的数据。我试过其中任何一个:

  1. 修改此方法以处理内部元组:

    class Explosion:
        ...
        def __iter__(self):
            return product(*self.fragments)
    
  2. 封装在处理转换的另一个对象中,但这不太可取:

    class CleanOutput:
        def __init__(self, it):
            self.it = it
    
        def next(self):
            for x in self.it:
                yield ?
    
    class Explosion:
        ...
        def __iter__(self):
            return CleanOutput(product(*self.fragments))
    

2 个答案:

答案 0 :(得分:1)

这并不容易,必须使用递归,但与主__iter__方法分开。这就是我最终的表现。 现在还有一个递归生成器_merge,由另一个生成器_flatten调用:

class Explosion:
    # ...

    def __iter__(self):
        def _flatten(container):
            def _merge(t):
                for te in t:
                    if isinstance(te, tuple):
                        for ite in _merge(te):
                            yield ite
                    else:
                        yield te

            for t in container:
                yield tuple(_merge(t))

        return _flatten(product(*self.fragments))

查看_flatten()函数的使用示例:

>>> list(itertools.product([1,2],[3,(4,(5,6))]))
[(1, 3), (1, (4, (5, 6))), (2, 3), (2, (4, (5, 6)))]
>>> list(_flatten(itertools.product([1,2],[3,(4,(5,6))])))
[(1, 3), (1, 4, 5, 6), (2, 3), (2, 4, 5, 6)]

答案 1 :(得分:0)

def gen(data):
   for item in data:
      if isinstance(item, tuple):
          for nested in gen(item):
              yield nested
      else:
          yield item

未经测试,但应该有效。