我已经实现了一个算法,用于在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
动态生成的数据。我试过其中任何一个:
修改此方法以处理内部元组:
class Explosion:
...
def __iter__(self):
return product(*self.fragments)
封装在处理转换的另一个对象中,但这不太可取:
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))
答案 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
未经测试,但应该有效。