我想定义一个python函数,它接受一个字典列表,其中一些键可以是列表,然后返回一个字典列表的列表,其中每个键是一个值,对应于所有选项的组合(一个选项是从每个列表中选择一个值)。
考虑以下输入:
input = [
{
"name": "A",
"option1": [1, 2],
"option2": ["a1", "a2"]
}
{
"name": "B",
"option1": [3, 4],
"option2": "b1"
}
]
给定这个输入,期望的输出将是:
output = [[{"name": "A", "option1": 1, "option2": "a1"}{"name": "B", "option1": 3, "option2": "b1"}]
[{"name": "A", "option1": 1, "option2": "a1"}{"name": "B", "option1": 4, "option2": "b1"}]
[{"name": "A", "option1": 1, "option2": "a2"}{"name": "B", "option1": 3, "option2": "b1"}]
[{"name": "A", "option1": 1, "option2": "a2"}{"name": "B", "option1": 4, "option2": "b1"}]
[{"name": "A", "option1": 2, "option2": "a1"}{"name": "B", "option1": 3, "option2": "b1"}]
[{"name": "A", "option1": 2, "option2": "a1"}{"name": "B", "option1": 4, "option2": "b1"}]
[{"name": "A", "option1": 2, "option2": "a2"}{"name": "B", "option1": 3, "option2": "b1"}]
[{"name": "A", "option1": 2, "option2": "a2"}{"name": "B", "option1": 4, "option2": "b1"}]]
让我们试一下。
import itertools
input = [
{
"name": "A",
"option1": [1, 2],
"option2": ["a1", "a2"]
},
{
"name": "B",
"option1": [3, 4],
"option2": "b1"
}
]
list_opts = [y
for x in input
for y in [x['option1']
if type(x['option1']) == list
else [x['option1']],
x['option2']
if type(x['option2']) == list
else [x['option2']]]]
list_combinations = list(itertools.product(*list_opts))
output = [[{"name": "A",
"option1": x[0],
"option2": x[1]},
{"name": "B",
"option1": x[2],
"option2": x[3]}]
for x in list_combinations]
这是我得到的。
[[{'name': 'A', 'option1': 1, 'option2': 'a1'},
{'name': 'B', 'option1': 3, 'option2': 'b1'}],
[{'name': 'A', 'option1': 1, 'option2': 'a1'},
{'name': 'B', 'option1': 4, 'option2': 'b1'}],
[{'name': 'A', 'option1': 1, 'option2': 'a2'},
{'name': 'B', 'option1': 3, 'option2': 'b1'}],
[{'name': 'A', 'option1': 1, 'option2': 'a2'},
{'name': 'B', 'option1': 4, 'option2': 'b1'}],
[{'name': 'A', 'option1': 2, 'option2': 'a1'},
{'name': 'B', 'option1': 3, 'option2': 'b1'}],
[{'name': 'A', 'option1': 2, 'option2': 'a1'},
{'name': 'B', 'option1': 4, 'option2': 'b1'}],
[{'name': 'A', 'option1': 2, 'option2': 'a2'},
{'name': 'B', 'option1': 3, 'option2': 'b1'}],
[{'name': 'A', 'option1': 2, 'option2': 'a2'},
{'name': 'B', 'option1': 4, 'option2': 'b1'}]]
虽然George的答案可能产生正确的输出,但如果将解决方案扩展到更多选项,则可能出现问题。
这是我想到的:
import copy
import itertools
input = [
{
"name": "A",
"option1": [1, 2],
"option2": ["a1", "a2"]
},
{
"name": "B",
"option1": [3, 4],
"option2": "b1"
}
]
def dictContainsListVals(dic):
return any([isinstance(val, list) for val in dic.values()])
def splitDict(dic):
flattenedDicts = [dic]
while any(dictContainsListVals(dic) for dic in flattenedDicts):
splitDict = flattenedDicts.pop(0)
for key, value in splitDict.items():
if isinstance(value, list):
for el in value:
dictCopy = copy.deepcopy(splitDict)
dictCopy[key] = el
flattenedDicts.append(dictCopy)
break
else:
flattenedDicts.append(splitDict)
return flattenedDicts
flattenedDicts = []
for dic in input:
flattenedDicts.append(splitDict(dic))
output = itertools.product(*flattenedDicts)
print(list(output))
输出:
[({'name': 'A', 'option1': 1, 'option2': 'a1'}, {'name': 'B', 'option1': 3, 'option2': 'b1'}),
({'name': 'A', 'option1': 1, 'option2': 'a1'}, {'name': 'B', 'option1': 4, 'option2': 'b1'}),
({'name': 'A', 'option1': 1, 'option2': 'a2'}, {'name': 'B', 'option1': 3, 'option2': 'b1'}),
({'name': 'A', 'option1': 1, 'option2': 'a2'}, {'name': 'B', 'option1': 4, 'option2': 'b1'}),
({'name': 'A', 'option1': 2, 'option2': 'a1'}, {'name': 'B', 'option1': 3, 'option2': 'b1'}),
({'name': 'A', 'option1': 2, 'option2': 'a1'}, {'name': 'B', 'option1': 4, 'option2': 'b1'}),
({'name': 'A', 'option1': 2, 'option2': 'a2'}, {'name': 'B', 'option1': 3, 'option2': 'b1'}),
({'name': 'A', 'option1': 2, 'option2': 'a2'}, {'name': 'B', 'option1': 4, 'option2': 'b1'})]