清除动态生成的嵌套元组

Clean dynamically generated nested Tuples

我有一个 class 其 __iter__() 方法 return 一个 itertools.product() 动态生成的数据。 此数据是任意嵌套字典的笛卡尔积,现在我需要将其展平,但以一种简化的方式聚合中间迭代器。

我正在尝试其中之一:

  1. 修改__iter__()以处理内部元组:

     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))
    

嗯,算法确实可以,但问题是最后的解包,例如:

(11, ..., (10.7, 104.75, ('N', True, False, 'B2B'), 99.01, ...), 1, 'SP', 7).

看看所有的嵌套!如何在 real-time 中删除它?在生成时... 我正在寻找一种检索方式:

(11, ..., 10.7, 104.75, 'N', True, False, 'B2B', 99.01, ..., 1, 'SP', 7).

最好最快的方法是什么? 谢谢!

编辑

实际上,我真正想要的是列表理解或生成器表达式甚至另一个生成器,因为我需要将它包含在可调用文件中,拦截itertools.product() 本身。我不仅仅需要 方式 来清理这些元组。所以它不是重复的。

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

未经测试,但应该可以。

这并不容易,必须使用递归,但与主要 __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)]