我的最初问题是要转换List
个Mapping
,其值是List
个值。转换后的列表必须包含属于单独词典的所有列表(即词典中的值)的笛卡尔积(换句话说,存在于同一目录中的列表的值是“耦合的”)。
基本上,如果您忽略字典的键,只需使用itertools.product
即可解决。
输入:
[
{
('B3G', 'B1'): [1.0, 2.0],
('B1G', 'B1'): [11.0, 12.0]
},
{
('B2G', 'B1'): [1.5, 2.5, 3.5]
}
]
输出:
[
{('B3G', 'B1'): 1.0, ('B1G', 'B1'): 11.0, ('B2G', 'B1'): 1.5},
{('B3G', 'B1'): 1.0, ('B1G', 'B1'): 11.0, ('B2G', 'B1'): 2.5},
{('B3G', 'B1'): 1.0, ('B1G', 'B1'): 11.0, ('B2G', 'B1'): 3.5},
{('B3G', 'B1'): 2.0, ('B1G', 'B1'): 12.0, ('B2G', 'B1'): 1.5},
{('B3G', 'B1'): 2.0, ('B1G', 'B1'): 12.0, ('B2G', 'B1'): 2.5},
{('B3G', 'B1'): 2.0, ('B1G', 'B1'): 12.0, ('B2G', 'B1'): 3.5}
]
为了使事情更加混乱,每个字典的键都是Tuple
个字符串。
这是一种可能的实现方式,可以使用class
隔离整个混乱局面。
@dataclass
class ParametricMapping:
"""Abstraction for multi-dimensional parametric mappings."""
mappings: List[Mapping[Tuple[str], Sequence[float]]] = field(default_factory=lambda: [{}])
@property
def combinations(self) -> List[Mapping[Tuple[str], float]]:
"""Cartesian product adapted to work with dictionaries, roughly similar to `itertools.product`."""
labels = [label for arg in self.mappings for label in tuple(arg.keys())]
pools = [list(map(tuple, zip(*arg.values()))) for arg in self.mappings]
def cartesian_product(*args):
"""Cartesian product similar to `itertools.product`"""
result = [[]]
for pool in args:
result = [x + [y] for x in result for y in pool]
return result
results = []
for term in cartesian_product(*pools):
results.append([pp for p in term for pp in p])
tmp = []
for r in results:
tmp.append({k: v for k, v in zip(labels, r)})
if len(tmp) == 0:
return [{}]
else:
return tmp
问题:我该如何改进它以使其更清洁(优先级1)和更快(#2)。