Reputation: 107
I am trying to create a dictionary using below code:
def func(inp):
return (dict(zip(inp.keys(), values)) for values in product(*inp.values()))
x ={'Key1': ['111', '42343'], 'key2': ['TEST', 'TESTTT123'], 'Key3': ['Cell Phone', 'e-Mail'], 'Key5': ['32142341', '[email protected]']}
func(x)
But It gave me a cartesian product
{'Key1': '111', 'Key2': 'TEST', 'Key3': 'Cell Phone', 'Key4': '32142341'}
{'Key1': '111', 'Key2': 'TEST', 'Key3': 'Cell Phone', 'Key4': '[email protected]'}
{'Key1': '111', 'Key2': 'TEST', 'Key3': 'e-Mail', 'Key4': '32142341'}
{'Key1': '111', 'Key2': 'TEST', 'Key3': 'e-Mail', 'Key4': '[email protected]'}
{'Key1': '111', 'Key2': 'TESTTT123', 'Key3': 'Cell Phone', 'Key4': '32142341'}
{'Key1': '111', 'Key2': 'TESTTT123', 'Key3': 'Cell Phone', 'Key4': '[email protected]'}
{'Key1': '111', 'Key2': 'TESTTT123', 'Key3': 'e-Mail', 'Key4': '32142341'}
{'Key1': '111', 'Key2': 'TESTTT123', 'Key3': 'e-Mail', 'Key4': '[email protected]'}
{'Key1': '42343', 'Key2': 'TEST', 'Key3': 'Cell Phone', 'Key4': '32142341'}
{'Key1': '42343', 'Key2': 'TEST', 'Key3': 'Cell Phone', 'Key4': '[email protected]'}
{'Key1': '42343', 'Key2': 'TEST', 'Key3': 'e-Mail', 'Key4': '32142341'}
{'Key1': '42343', 'Key2': 'TEST', 'Key3': 'e-Mail', 'Key4': '[email protected]'}
{'Key1': '42343', 'Key2': 'TESTTT123', 'Key3': 'Cell Phone', 'Key4': '32142341'}
{'Key1': '42343', 'Key2': 'TESTTT123', 'Key3': 'Cell Phone', 'Key4': '[email protected]'}
{'Key1': '42343', 'Key2': 'TESTTT123', 'Key3': 'e-Mail', 'Key4': '32142341'}
{'Key1': '42343', 'Key2': 'TESTTT123', 'Key3': 'e-Mail', 'Key4': '[email protected]'}
However output req is:
{'Key1': '111', 'Key2': 'TEST', 'Key3': 'Cell Phone', 'Key4': '32142341'}
{'Key1': '42343', 'Key2': 'TESTTT123', 'Key3': 'e-Mail', 'Key4': '[email protected]'}
any help how to avoid cartesian product?
Upvotes: 1
Views: 43
Reputation: 106598
Your solution is pretty close but unnecessarily calls the cartesian product function. You can instead zip directly the values of the input dict so that you can iterate through them to create sub-dicts by zipping them with the keys of the input dict:
def func(inp):
return (dict(zip(inp, values)) for values in zip(*inp.values()))
Upvotes: 1
Reputation: 5237
Just loop through the length of the lists using range
and use a dictionary comprehension to construct the individual dicts, selecting the i
th element of the list each time:
def func(inp):
return ({k: v[i] for k, v in inp.items()} for i in range(len(list(inp.values())[0])))
x = {'Key1': ['111', '42343'], 'key2': ['TEST', 'TESTTT123'], 'Key3': ['Cell Phone', 'e-Mail'], 'Key4': ['32142341', '[email protected]']}
res = func(x)
for r in res:
print(r)
Output:
{'Key1': '111', 'Key2': 'TEST', 'Key3': 'Cell Phone', 'Key4': '32142341'}
{'Key1': '42343', 'Key2': 'TESTTT123', 'Key3': 'e-Mail', 'Key4': '[email protected]'}
This uses the length of the list of the first key/value pair, and assumes all the lists are of the equal length.
Upvotes: 1