我需要帮助从元组列表生成组合,其中每个元组包含索引 0 处的字符串和索引 1 处的值列表。例如,考虑以下设置:
params = ['sn', 'tp', 'v1', 'temp', 'slew']
list_tuple = [('Serial Number', [12345]),
('Test Points', ['TestpointA', 'TestpointC']),
('Voltage_1', [3.0, 3.3, 3.6, 0.0]),
('Temperature Setpoint', [0, 60]),
('Slew_1', [200, 400, 800, 1600, 3200, 6400])]
我一直在使用嵌套循环来生成这些参数的所有可能组合,如图所示:
def generate_combinations(test_tuple, params):
for sn in test_tuple[0][1]:
for tp in test_tuple[1][1]:
for v in test_tuple[2][1]:
for temp in test_tuple[3][1]:
for slew in test_tuple[4][1]:
print(f'{params[0]}: ', sn)
print(f'{params[1]}: ', tp)
print(f'{params[2]}: ', v)
print(f'{params[3]}: ', temp)
print(f'{params[4]}: ', slew)
print('\n')
generate_combinations(list_tuple, params)
此方法有效,但不可扩展,因为嵌套循环的深度对应于
params
列表的长度,该长度可能会有所不同。元组中每个列表的长度也可以改变。我需要一个更动态的解决方案,最好没有显式嵌套循环。
我尝试使用递归,但没有达到预期的结果:
def not_working(list_tuple):
for i in list_tuple:
if isinstance(i, tuple):
print(i[0])
not_working(i[1])
else:
print(i)
print('\n')
not_working(list_tuple)
如何在不使用显式嵌套循环的情况下动态实现所需的输出,无论
list_tuple
中的元组数量或每个子列表中的元素数量如何?
您可以使用
itertools.product
:
import itertools
data = [('Serial Number', [12345]), ('Test Points', ['TestpointA', 'TestpointC']), ('Voltage_1', [3.0, 3.3, 3.6, 0.0]), ('Temperature Setpoint', [0, 60]), ('Slew_1', [200, 400, 800, 1600, 3200, 6400])]
params = ['sn', 'tp', 'v1', 'temp', 'slew']
for i in itertools.product(*[b for _, b in data]):
print('\n'.join(f'{a}:{b}' for a, b in zip(params, i)))
print('-'*20)
输出(前三个结果):
sn:12345
tp:TestpointA
v1:3.0
temp:0
slew:200
--------------------
sn:12345
tp:TestpointA
v1:3.0
temp:0
slew:400
--------------------
sn:12345
tp:TestpointA
v1:3.0
temp:0
slew:800
--------------------
...
虽然
itertools.product
(也许)是这个问题最干净的解决方案,但可以使用带有生成器的简单递归函数。
d
和data
有什么区别?在递归函数中,d
在每次迭代时都会通过列表切片(d[i+1:]
)进行变异。由于 d
的长度减小,而 len(d)
求的是函数作用域中声明的对象 d
的长度,所以它不会求出存储原始数据的列表的长度,而是求当前值传递给 combination
,每次调用都会减少。
def combination(d, current = []):
if len(current) == len(data):
yield current
else:
for i, a in enumerate(d):
for c in a:
yield from combination(d[i+1:], current = current+[c])
for i in combination([b for _, b in data]):
print('\n'.join(f'{a}:{b}' for a, b in zip(params, i)))
print('-'*20)
输出(前三个结果):
sn:12345
tp:TestpointA
v1:3.0
temp:0
slew:200
--------------------
sn:12345
tp:TestpointA
v1:3.0
temp:0
slew:400
--------------------
sn:12345
tp:TestpointA
v1:3.0
temp:0
slew:800
--------------------