Cartesian product of nested dictionaries of lists - python
I have some code that generates all the combinations for a dictionary of lists
import itertools
import collections
def gen_combinations(d):
keys, values = d.keys(), d.values()
combinations = itertools.product(*values)
for c in combinations:
yield dict(zip(keys, c))
Let's say I have a dictionary A like
A = {'a': [0, 1],
'b': [2, 3, 4]}
It yields:
{'a': 0, 'b': 2}
{'a': 0, 'b': 3}
{'a': 0, 'b': 4}
{'a': 1, 'b': 2}
{'a': 1, 'b': 3}
{'a': 1, 'b': 4}
Now I'd like it to work with nested dictionary of lists like
B = {'s1': {'a': [0, 1],
'b': [0, 1, 2] },
's2': {'c': [0, 1],
'd': [0, 1] }}
which should yield something like:
{'s1': {'a': 0, 'b': 0},
's2': {'c': 0, 'd': 0}}
{'s1': {'a': 0, 'b': 0},
's2': {'c': 0, 'd': 1}}
{'s1': {'a': 0, 'b': 0},
's2': {'c': 1, 'd': 0}}
{'s1': {'a': 0, 'b': 0},
's2': {'c': 1, 'd': 1}}
and so on for all the combinations...
I'm looking for an elegant way to do this. Don't have any particular performance restrictions, they are small dictionaries.
Just create the product of the output of gen_combinations() for each key in the outer dictionary:
def gen_dict_combinations(d):
keys, values = d.keys(), d.values()
for c in itertools.product(*(gen_combinations(v) for v in values)):
yield dict(zip(keys, c))
This is basically the same pattern, only now instead of using values directly, we use the output of gen_combinations():
>>> for c in gen_dict_combinations(B):
... print(c)
...
{'s1': {'a': 0, 'b': 0}, 's2': {'c': 0, 'd': 0}}
{'s1': {'a': 0, 'b': 0}, 's2': {'c': 0, 'd': 1}}
{'s1': {'a': 0, 'b': 0}, 's2': {'c': 1, 'd': 0}}
{'s1': {'a': 0, 'b': 0}, 's2': {'c': 1, 'd': 1}}
{'s1': {'a': 0, 'b': 1}, 's2': {'c': 0, 'd': 0}}
{'s1': {'a': 0, 'b': 1}, 's2': {'c': 0, 'd': 1}}
{'s1': {'a': 0, 'b': 1}, 's2': {'c': 1, 'd': 0}}
{'s1': {'a': 0, 'b': 1}, 's2': {'c': 1, 'd': 1}}
{'s1': {'a': 0, 'b': 2}, 's2': {'c': 0, 'd': 0}}
{'s1': {'a': 0, 'b': 2}, 's2': {'c': 0, 'd': 1}}
{'s1': {'a': 0, 'b': 2}, 's2': {'c': 1, 'd': 0}}
{'s1': {'a': 0, 'b': 2}, 's2': {'c': 1, 'd': 1}}
{'s1': {'a': 1, 'b': 0}, 's2': {'c': 0, 'd': 0}}
{'s1': {'a': 1, 'b': 0}, 's2': {'c': 0, 'd': 1}}
{'s1': {'a': 1, 'b': 0}, 's2': {'c': 1, 'd': 0}}
{'s1': {'a': 1, 'b': 0}, 's2': {'c': 1, 'd': 1}}
{'s1': {'a': 1, 'b': 1}, 's2': {'c': 0, 'd': 0}}
{'s1': {'a': 1, 'b': 1}, 's2': {'c': 0, 'd': 1}}
{'s1': {'a': 1, 'b': 1}, 's2': {'c': 1, 'd': 0}}
{'s1': {'a': 1, 'b': 1}, 's2': {'c': 1, 'd': 1}}
{'s1': {'a': 1, 'b': 2}, 's2': {'c': 0, 'd': 0}}
{'s1': {'a': 1, 'b': 2}, 's2': {'c': 0, 'd': 1}}
{'s1': {'a': 1, 'b': 2}, 's2': {'c': 1, 'd': 0}}
{'s1': {'a': 1, 'b': 2}, 's2': {'c': 1, 'd': 1}}
Ended up with a recursive version for arbitrarily nested dictionaries:
import itertools
def gen_combinations(d):
keys, values = d.keys(), d.values()
values_choices = (gen_combinations(v) if isinstance(v, dict) else v for v in values)
for comb in itertools.product(*values_choices):
yield dict(zip(keys, comb))
B = {'s1': {'a': [0, 1],
'b': [0, 1, 2] },
's2': {'c': [0, 1],
'd': [0, 1] }}
for c in gen_combinations(B):
print(c)
Output:
{'s1': {'a': 0, 'b': 0}, 's2': {'c': 0, 'd': 0}}
{'s1': {'a': 0, 'b': 0}, 's2': {'c': 0, 'd': 1}}
{'s1': {'a': 0, 'b': 0}, 's2': {'c': 1, 'd': 0}}
{'s1': {'a': 0, 'b': 0}, 's2': {'c': 1, 'd': 1}}
{'s1': {'a': 0, 'b': 1}, 's2': {'c': 0, 'd': 0}}
{'s1': {'a': 0, 'b': 1}, 's2': {'c': 0, 'd': 1}}
{'s1': {'a': 0, 'b': 1}, 's2': {'c': 1, 'd': 0}}
{'s1': {'a': 0, 'b': 1}, 's2': {'c': 1, 'd': 1}}
{'s1': {'a': 0, 'b': 2}, 's2': {'c': 0, 'd': 0}}
{'s1': {'a': 0, 'b': 2}, 's2': {'c': 0, 'd': 1}}
{'s1': {'a': 0, 'b': 2}, 's2': {'c': 1, 'd': 0}}
{'s1': {'a': 0, 'b': 2}, 's2': {'c': 1, 'd': 1}}
{'s1': {'a': 1, 'b': 0}, 's2': {'c': 0, 'd': 0}}
{'s1': {'a': 1, 'b': 0}, 's2': {'c': 0, 'd': 1}}
{'s1': {'a': 1, 'b': 0}, 's2': {'c': 1, 'd': 0}}
{'s1': {'a': 1, 'b': 0}, 's2': {'c': 1, 'd': 1}}
{'s1': {'a': 1, 'b': 1}, 's2': {'c': 0, 'd': 0}}
{'s1': {'a': 1, 'b': 1}, 's2': {'c': 0, 'd': 1}}
{'s1': {'a': 1, 'b': 1}, 's2': {'c': 1, 'd': 0}}
{'s1': {'a': 1, 'b': 1}, 's2': {'c': 1, 'd': 1}}
{'s1': {'a': 1, 'b': 2}, 's2': {'c': 0, 'd': 0}}
{'s1': {'a': 1, 'b': 2}, 's2': {'c': 0, 'd': 1}}
{'s1': {'a': 1, 'b': 2}, 's2': {'c': 1, 'd': 0}}
{'s1': {'a': 1, 'b': 2}, 's2': {'c': 1, 'd': 1}}
I extended Martijn Pieters answer so that the function can also handle non-iterable values in the nested dictionary. So the code below works on nested dicts (just one level of nesting though) that look like this:
dictionary = {
'a': 31415,
'b': 'strings too',
'c': [1, 2, 3],
'd': {'e': [1, 2, 3], 'f': 42, 'g': 'strings here too'}
}
from itertools import product
def _gen_combinations(d):
keys, values = d.keys(), d.values()
list_keys = [k for k in keys if isinstance(d[k], list)]
nonlist_keys = [k for k in keys if k not in list_keys]
list_values = [v for v in values if isinstance(v, list)]
nonlist_values = [v for v in values if v not in list_values]
combinations = product(*list_values)
for c in combinations:
result = dict(zip(list_keys, c))
result.update({k: v for k, v in zip(nonlist_keys, nonlist_values)})
yield result
def generate_dict_combinations(d):
keys, values = d.keys(), d.values()
dict_values = [v for v in values if isinstance(v, dict)]
dict_keys = [k for k in keys if isinstance(d[k], dict)]
nondict_values = [v for v in values if v not in dict_values]
nondict_keys = [k for k in keys if k not in dict_keys]
for c in product(*(_gen_combinations(v) for v in dict_values)):
result = dict(zip(dict_keys, c))
result.update({k: v for k, v in zip(nondict_keys, nondict_values)})
yield result
Related
Iterating over combinations of integer values from a dict
I have a dict I'm trying to loop through which stores integer values: myDict = {"a":1,"b":2,"c":3} And I'm trying to loop through every combination of these integers from 1 to their value. For example: {"a":1,"b":1,"c":1} {"a":1,"b":1,"c":2} {"a":1,"b":1,"c":3} {"a":1,"b":2,"c":1} {"a":1,"b":2,"c":2} And so on... Ending at their max values at the start while going through all the combinations. Is there an elegant way to this that applies to any size dictionary? : myDict = {"a":1,"b":2,"c":3,"d":5} I'm currently doing this with nested if statements that edit a clone dictionary, so any solution setting dict values would work :) : copyDict["c"] = 2
Yes, this will do it, for any size input (that fits in memory, of course): import itertools myDict = {"a":1,"b":2,"c":3,"d":5} keys = list(myDict.keys()) ranges = tuple(range(1,k+1) for k in myDict.values()) outs = [dict(zip(keys,s)) for s in itertools.product(*ranges)] print(outs) You can actually replace *ranges with the *(range(1,k+1) for k in myDict.values()) and reduce it by one line, but it's not easier to read.
Another way with itertools.product: >>> [dict(zip(myDict.keys(), p)) for p in itertools.product(myDict.values(), repeat=len(myDict))] [{'a': 1, 'b': 1, 'c': 1}, {'a': 1, 'b': 1, 'c': 2}, {'a': 1, 'b': 1, 'c': 3}, {'a': 1, 'b': 2, 'c': 1}, {'a': 1, 'b': 2, 'c': 2}, {'a': 1, 'b': 2, 'c': 3}, {'a': 1, 'b': 3, 'c': 1}, {'a': 1, 'b': 3, 'c': 2}, {'a': 1, 'b': 3, 'c': 3}, {'a': 2, 'b': 1, 'c': 1}, {'a': 2, 'b': 1, 'c': 2}, {'a': 2, 'b': 1, 'c': 3}, {'a': 2, 'b': 2, 'c': 1}, {'a': 2, 'b': 2, 'c': 2}, {'a': 2, 'b': 2, 'c': 3}, {'a': 2, 'b': 3, 'c': 1}, {'a': 2, 'b': 3, 'c': 2}, {'a': 2, 'b': 3, 'c': 3}, {'a': 3, 'b': 1, 'c': 1}, {'a': 3, 'b': 1, 'c': 2}, {'a': 3, 'b': 1, 'c': 3}, {'a': 3, 'b': 2, 'c': 1}, {'a': 3, 'b': 2, 'c': 2}, {'a': 3, 'b': 2, 'c': 3}, {'a': 3, 'b': 3, 'c': 1}, {'a': 3, 'b': 3, 'c': 2}, {'a': 3, 'b': 3, 'c': 3}]
Python create combinations of dictionary
I would like to convert a Python dictionary of the following form: D = {'a':[1,2,3], 'b':[0.1,0.5], 'c':[10,20]} into a list of dictionaries the following form: E = [{a:1,b:0.1,c:10}, {a:1,b:0.1,c:20},{a:1,b:0.5,c:10}, ...., {a:3,b:0.5,c:20}] I have tried using itertools but I do not understand how to use it to make combinations of dictionaries.
Here is a solution: import itertools D = {'a':[1,2,3], 'b':[0.1,0.5], 'c':[10,20]} E = [dict(zip(D.keys(), a)) for a in itertools.product(*D.values())] This yields: E= [{'a': 1, 'b': 0.1, 'c': 10}, {'a': 1, 'b': 0.1, 'c': 20}, {'a': 1, 'b': 0.5, 'c': 10}, {'a': 1, 'b': 0.5, 'c': 20}, {'a': 2, 'b': 0.1, 'c': 10}, {'a': 2, 'b': 0.1, 'c': 20}, {'a': 2, 'b': 0.5, 'c': 10}, {'a': 2, 'b': 0.5, 'c': 20}, {'a': 3, 'b': 0.1, 'c': 10}, {'a': 3, 'b': 0.1, 'c': 20}, {'a': 3, 'b': 0.5, 'c': 10}, {'a': 3, 'b': 0.5, 'c': 20}] Edit: Removed ordered dict as Aran points out, here is documentation to support it:Python dictionary: are keys() and values() always the same order?
Why not just: from itertools import product D = {'a':[1,2,3], 'b':[0.1,0.5], 'c':[10,20]} print([dict(zip(D.keys(),v)) for v in product(*D.values())]) Output: [{'a': 1, 'b': 0.1, 'c': 10}, {'a': 1, 'b': 0.1, 'c': 20}, {'a': 1, 'b': 0.5, 'c': 10}, {'a': 1, 'b': 0.5, 'c': 20}, {'a': 2, 'b': 0.1, 'c': 10}, {'a': 2, 'b': 0.1, 'c': 20}, {'a': 2, 'b': 0.5, 'c': 10}, {'a': 2, 'b': 0.5, 'c': 20}, {'a': 3, 'b': 0.1, 'c': 10}, {'a': 3, 'b': 0.1, 'c': 20}, {'a': 3, 'b': 0.5, 'c': 10}, {'a': 3, 'b': 0.5, 'c': 20}]
One option is to simply use nested for loops; if the original data is not too big, then this will work fine and you won't need itertools to get it working. >>> origin = { 'a': [1, 2, 3], 'b': [0.1, 0.5], 'c': [10, 20], } >>> result = [ { 'a': a, 'b': b, 'c': c, } for a in origin['a'] for b in origin['b'] for c in origin['c']] >>> result [{'a': 1, 'b': 0.1, 'c': 10}, {'a': 1, 'b': 0.1, 'c': 20}, {'a': 1, 'b': 0.5, 'c': 10}, {'a': 1, 'b': 0.5, 'c': 20}, {'a': 2, 'b': 0.1, 'c': 10}, {'a': 2, 'b': 0.1, 'c': 20}, {'a': 2, 'b': 0.5, 'c': 10}, {'a': 2, 'b': 0.5, 'c': 20}, {'a': 3, 'b': 0.1, 'c': 10}, {'a': 3, 'b': 0.1, 'c': 20}, {'a': 3, 'b': 0.5, 'c': 10}, {'a': 3, 'b': 0.5, 'c': 20}]
I developed a round about answer parameter_values_each = {'a':[1,2,3], 'b':[0.1,0.5], 'c':[10,20]} param_possibilities = [] for name in parameter_values_each: temp = [] for val in parameter_values_each[name]: temp.append((name,val)) param_possibilities.append(temp) result = list(itertools.product(*param_possibilities)) print result
Long way with no itertools (or this is what going on inside product): D = {'a': [1, 2, 3], 'b': [0.1, 0.5], 'c': [10, 20]} E = [] list_of_keys = list(D.keys()) list_of_lengths = [len(D[key]) for key in list_of_keys] product_number = 1 for length in list_of_lengths: product_number *= length for n in range(product_number): index = n index_list = [] for length in reversed(list_of_lengths): index_list.insert(0, index % length) index = index // length keys_with_values = {} for j, key in enumerate(list_of_keys): keys_with_values[key] = D[key][index_list[j]] E.append(keys_with_values) for e in E: print(e) Result: {'a': 1, 'b': 0.1, 'c': 10} {'a': 1, 'b': 0.1, 'c': 20} {'a': 1, 'b': 0.5, 'c': 10} {'a': 1, 'b': 0.5, 'c': 20} {'a': 2, 'b': 0.1, 'c': 10} {'a': 2, 'b': 0.1, 'c': 20} {'a': 2, 'b': 0.5, 'c': 10} {'a': 2, 'b': 0.5, 'c': 20} {'a': 3, 'b': 0.1, 'c': 10} {'a': 3, 'b': 0.1, 'c': 20} {'a': 3, 'b': 0.5, 'c': 10} {'a': 3, 'b': 0.5, 'c': 20}
Flatten product of two dictionary lists [duplicate]
This question already has answers here: How do I merge two dictionaries in a single expression in Python? (43 answers) Closed 5 years ago. I have two lists of dictionaries which I am trying to get the product of: from itertools import product list1 = [{'A': 1, 'B': 1}, {'A': 2, 'B': 2}, {'A': 2, 'B': 1}, {'A': 1, 'B': 2}] list2 = [{'C': 1, 'D': 1}, {'C': 1, 'D': 2}] for p in product(list1, list2): print p and this gives me the output: ({'A': 1, 'B': 1}, {'C': 1, 'D': 1}) ({'A': 1, 'B': 1}, {'C': 1, 'D': 2}) ({'A': 2, 'B': 2}, {'C': 1, 'D': 1}) ({'A': 2, 'B': 2}, {'C': 1, 'D': 2}) ({'A': 2, 'B': 1}, {'C': 1, 'D': 1}) ({'A': 2, 'B': 1}, {'C': 1, 'D': 2}) ({'A': 1, 'B': 2}, {'C': 1, 'D': 1}) ({'A': 1, 'B': 2}, {'C': 1, 'D': 2}) How would I flatten these so the output is a single dict rather than a tuple of dicts?: {'A': 1, 'B': 1, 'C': 1, 'D': 1} {'A': 1, 'B': 1, 'C': 1, 'D': 2} {'A': 2, 'B': 2, 'C': 1, 'D': 1} {'A': 2, 'B': 2, 'C': 1, 'D': 2} {'A': 2, 'B': 1, 'C': 1, 'D': 1} {'A': 2, 'B': 1, 'C': 1, 'D': 2} {'A': 1, 'B': 2, 'C': 1, 'D': 1} {'A': 1, 'B': 2, 'C': 1, 'D': 2}
Looks like you want to merge the dictionaries for p1, p2 in product(list1, list2): merged = {**p1, **p2} print(merged) In earlier versions of Python, you can't merge with this expression. Use p1.update(p2) instead.
Python, not able to append to a list from a recursive function
I am in the mid-way of writing a code to find all possible solutions of a input similar like "a&b|c!d|a", where a,b,c,d all are booleans and &-and, |-or !-not are the operators. By solution I mean the set of values of these variables which makes the input expression give True. I am able to print all possible combinations of the variables, but I am not able to retain them (in this case, in a list) for later use. What's wrong in the way I am doing it? Are there better ways to store them? generate_combination is the method in which I am trying to do this. Code: import operator # global all_combinations all_combinations=[] answers=[] def solve(combination, input, rank): try: substituted_str="" for i in input: if i in combination: substituted_str+=combination[i] else: substituted_str+=i print substituted_str # for item in rank: except: pass def generate_combination(variables,comb_dict, length, current_index): if len(comb_dict)==length: print comb_dict #Each combination , coming out right all_combinations.append(comb_dict) print all_combinations,"\n" #This is not working as expected else: for i in [1,0]: comb_dict[variables[current_index]]=i generate_combination(variables,comb_dict, length,current_index+1) comb_dict.pop(variables[current_index], None) def main(input,variables,order): rank=sorted(order.items(), key=operator.itemgetter(1)) generate_combination(variables, {}, len(variables), 0) for combination in all_combinations: print combination ans=solve(combination, input, rank) ans=[] answers.extend(ans) # for answer in answers: # print answer def nothing(): pass if __name__ == '__main__': # print "Enter your symbols for :\n" # And=raw_input("And = ") # Or=raw_input("Or = ") # Not=raw_input("Not = ") # input_str=raw_input("Enter the expression :") And,Or,Not,input_str='&','|','!','a&b|c!d|a' input_str=input_str.replace(" ","") mapping={And:"&", Or:"|", Not:"!"} order={"&":3, "|":2, "!":1} variables=[] processed_str="" for i in input_str: if i in mapping: processed_str+=mapping[i] else: processed_str+=i variables.append(i) variables=list(set(variables)) print "Reconstituted string : ",processed_str print "Variables : ",variables,"\n" main(processed_str,variables,order) Current Output: Reconstituted string : a&b|c!d|a Variables : ['a', 'c', 'b', 'd'] {'a': 1, 'c': 1, 'b': 1, 'd': 1} [{'a': 1, 'c': 1, 'b': 1, 'd': 1}] {'a': 1, 'c': 1, 'b': 1, 'd': 0} [{'a': 1, 'c': 1, 'b': 1, 'd': 0}, {'a': 1, 'c': 1, 'b': 1, 'd': 0}] {'a': 1, 'c': 1, 'b': 0, 'd': 1} [{'a': 1, 'c': 1, 'b': 0, 'd': 1}, {'a': 1, 'c': 1, 'b': 0, 'd': 1}, {'a': 1, 'c': 1, 'b': 0, 'd': 1}] {'a': 1, 'c': 1, 'b': 0, 'd': 0} [{'a': 1, 'c': 1, 'b': 0, 'd': 0}, {'a': 1, 'c': 1, 'b': 0, 'd': 0}, {'a': 1, 'c': 1, 'b': 0, 'd': 0}, {'a': 1, 'c': 1, 'b': 0, 'd': 0}] {'a': 1, 'c': 0, 'b': 1, 'd': 1} [{'a': 1, 'c': 0, 'b': 1, 'd': 1}, {'a': 1, 'c': 0, 'b': 1, 'd': 1}, {'a': 1, 'c': 0, 'b': 1, 'd': 1}, {'a': 1, 'c': 0, 'b': 1, 'd': 1}, {'a': 1, 'c': 0, 'b': 1, 'd': 1}] {'a': 1, 'c': 0, 'b': 1, 'd': 0} [{'a': 1, 'c': 0, 'b': 1, 'd': 0}, {'a': 1, 'c': 0, 'b': 1, 'd': 0}, {'a': 1, 'c': 0, 'b': 1, 'd': 0}, {'a': 1, 'c': 0, 'b': 1, 'd': 0}, {'a': 1, 'c': 0, 'b': 1, 'd': 0}, {'a': 1, 'c': 0, 'b': 1, 'd': 0}] {'a': 1, 'c': 0, 'b': 0, 'd': 1} [{'a': 1, 'c': 0, 'b': 0, 'd': 1}, {'a': 1, 'c': 0, 'b': 0, 'd': 1}, {'a': 1, 'c': 0, 'b': 0, 'd': 1}, {'a': 1, 'c': 0, 'b': 0, 'd': 1}, {'a': 1, 'c': 0, 'b': 0, 'd': 1}, {'a': 1, 'c': 0, 'b': 0, 'd': 1}, {'a': 1, 'c': 0, 'b': 0, 'd': 1}] {'a': 1, 'c': 0, 'b': 0, 'd': 0} [{'a': 1, 'c': 0, 'b': 0, 'd': 0}, {'a': 1, 'c': 0, 'b': 0, 'd': 0}, {'a': 1, 'c': 0, 'b': 0, 'd': 0}, {'a': 1, 'c': 0, 'b': 0, 'd': 0}, {'a': 1, 'c': 0, 'b': 0, 'd': 0}, {'a': 1, 'c': 0, 'b': 0, 'd': 0}, {'a': 1, 'c': 0, 'b': 0, 'd': 0}, {'a': 1, 'c': 0, 'b': 0, 'd': 0}] {'a': 0, 'c': 1, 'b': 1, 'd': 1} [{'a': 0, 'c': 1, 'b': 1, 'd': 1}, {'a': 0, 'c': 1, 'b': 1, 'd': 1}, {'a': 0, 'c': 1, 'b': 1, 'd': 1}, {'a': 0, 'c': 1, 'b': 1, 'd': 1}, {'a': 0, 'c': 1, 'b': 1, 'd': 1}, {'a': 0, 'c': 1, 'b': 1, 'd': 1}, {'a': 0, 'c': 1, 'b': 1, 'd': 1}, {'a': 0, 'c': 1, 'b': 1, 'd': 1}, {'a': 0, 'c': 1, 'b': 1, 'd': 1}] {'a': 0, 'c': 1, 'b': 1, 'd': 0} [{'a': 0, 'c': 1, 'b': 1, 'd': 0}, {'a': 0, 'c': 1, 'b': 1, 'd': 0}, {'a': 0, 'c': 1, 'b': 1, 'd': 0}, {'a': 0, 'c': 1, 'b': 1, 'd': 0}, {'a': 0, 'c': 1, 'b': 1, 'd': 0}, {'a': 0, 'c': 1, 'b': 1, 'd': 0}, {'a': 0, 'c': 1, 'b': 1, 'd': 0}, {'a': 0, 'c': 1, 'b': 1, 'd': 0}, {'a': 0, 'c': 1, 'b': 1, 'd': 0}, {'a': 0, 'c': 1, 'b': 1, 'd': 0}] {'a': 0, 'c': 1, 'b': 0, 'd': 1} [{'a': 0, 'c': 1, 'b': 0, 'd': 1}, {'a': 0, 'c': 1, 'b': 0, 'd': 1}, {'a': 0, 'c': 1, 'b': 0, 'd': 1}, {'a': 0, 'c': 1, 'b': 0, 'd': 1}, {'a': 0, 'c': 1, 'b': 0, 'd': 1}, {'a': 0, 'c': 1, 'b': 0, 'd': 1}, {'a': 0, 'c': 1, 'b': 0, 'd': 1}, {'a': 0, 'c': 1, 'b': 0, 'd': 1}, {'a': 0, 'c': 1, 'b': 0, 'd': 1}, {'a': 0, 'c': 1, 'b': 0, 'd': 1}, {'a': 0, 'c': 1, 'b': 0, 'd': 1}] {'a': 0, 'c': 1, 'b': 0, 'd': 0} [{'a': 0, 'c': 1, 'b': 0, 'd': 0}, {'a': 0, 'c': 1, 'b': 0, 'd': 0}, {'a': 0, 'c': 1, 'b': 0, 'd': 0}, {'a': 0, 'c': 1, 'b': 0, 'd': 0}, {'a': 0, 'c': 1, 'b': 0, 'd': 0}, {'a': 0, 'c': 1, 'b': 0, 'd': 0}, {'a': 0, 'c': 1, 'b': 0, 'd': 0}, {'a': 0, 'c': 1, 'b': 0, 'd': 0}, {'a': 0, 'c': 1, 'b': 0, 'd': 0}, {'a': 0, 'c': 1, 'b': 0, 'd': 0}, {'a': 0, 'c': 1, 'b': 0, 'd': 0}, {'a': 0, 'c': 1, 'b': 0, 'd': 0}] {'a': 0, 'c': 0, 'b': 1, 'd': 1} [{'a': 0, 'c': 0, 'b': 1, 'd': 1}, {'a': 0, 'c': 0, 'b': 1, 'd': 1}, {'a': 0, 'c': 0, 'b': 1, 'd': 1}, {'a': 0, 'c': 0, 'b': 1, 'd': 1}, {'a': 0, 'c': 0, 'b': 1, 'd': 1}, {'a': 0, 'c': 0, 'b': 1, 'd': 1}, {'a': 0, 'c': 0, 'b': 1, 'd': 1}, {'a': 0, 'c': 0, 'b': 1, 'd': 1}, {'a': 0, 'c': 0, 'b': 1, 'd': 1}, {'a': 0, 'c': 0, 'b': 1, 'd': 1}, {'a': 0, 'c': 0, 'b': 1, 'd': 1}, {'a': 0, 'c': 0, 'b': 1, 'd': 1}, {'a': 0, 'c': 0, 'b': 1, 'd': 1}] {'a': 0, 'c': 0, 'b': 1, 'd': 0} [{'a': 0, 'c': 0, 'b': 1, 'd': 0}, {'a': 0, 'c': 0, 'b': 1, 'd': 0}, {'a': 0, 'c': 0, 'b': 1, 'd': 0}, {'a': 0, 'c': 0, 'b': 1, 'd': 0}, {'a': 0, 'c': 0, 'b': 1, 'd': 0}, {'a': 0, 'c': 0, 'b': 1, 'd': 0}, {'a': 0, 'c': 0, 'b': 1, 'd': 0}, {'a': 0, 'c': 0, 'b': 1, 'd': 0}, {'a': 0, 'c': 0, 'b': 1, 'd': 0}, {'a': 0, 'c': 0, 'b': 1, 'd': 0}, {'a': 0, 'c': 0, 'b': 1, 'd': 0}, {'a': 0, 'c': 0, 'b': 1, 'd': 0}, {'a': 0, 'c': 0, 'b': 1, 'd': 0}, {'a': 0, 'c': 0, 'b': 1, 'd': 0}] {'a': 0, 'c': 0, 'b': 0, 'd': 1} [{'a': 0, 'c': 0, 'b': 0, 'd': 1}, {'a': 0, 'c': 0, 'b': 0, 'd': 1}, {'a': 0, 'c': 0, 'b': 0, 'd': 1}, {'a': 0, 'c': 0, 'b': 0, 'd': 1}, {'a': 0, 'c': 0, 'b': 0, 'd': 1}, {'a': 0, 'c': 0, 'b': 0, 'd': 1}, {'a': 0, 'c': 0, 'b': 0, 'd': 1}, {'a': 0, 'c': 0, 'b': 0, 'd': 1}, {'a': 0, 'c': 0, 'b': 0, 'd': 1}, {'a': 0, 'c': 0, 'b': 0, 'd': 1}, {'a': 0, 'c': 0, 'b': 0, 'd': 1}, {'a': 0, 'c': 0, 'b': 0, 'd': 1}, {'a': 0, 'c': 0, 'b': 0, 'd': 1}, {'a': 0, 'c': 0, 'b': 0, 'd': 1}, {'a': 0, 'c': 0, 'b': 0, 'd': 1}] {'a': 0, 'c': 0, 'b': 0, 'd': 0} [{'a': 0, 'c': 0, 'b': 0, 'd': 0}, {'a': 0, 'c': 0, 'b': 0, 'd': 0}, {'a': 0, 'c': 0, 'b': 0, 'd': 0}, {'a': 0, 'c': 0, 'b': 0, 'd': 0}, {'a': 0, 'c': 0, 'b': 0, 'd': 0}, {'a': 0, 'c': 0, 'b': 0, 'd': 0}, {'a': 0, 'c': 0, 'b': 0, 'd': 0}, {'a': 0, 'c': 0, 'b': 0, 'd': 0}, {'a': 0, 'c': 0, 'b': 0, 'd': 0}, {'a': 0, 'c': 0, 'b': 0, 'd': 0}, {'a': 0, 'c': 0, 'b': 0, 'd': 0}, {'a': 0, 'c': 0, 'b': 0, 'd': 0}, {'a': 0, 'c': 0, 'b': 0, 'd': 0}, {'a': 0, 'c': 0, 'b': 0, 'd': 0}, {'a': 0, 'c': 0, 'b': 0, 'd': 0}, {'a': 0, 'c': 0, 'b': 0, 'd': 0}]
I think the problem is that all the items in your all_combinations list are pointed to the same comb_dict, you are overwriting each element in every call of generate_combination. Try to make a copy of the comb_dict: all_combinations.append(comb_dict.copy())
Permutations of dictionary in python
I have a dictionary like this - {'A': 0, 'B': 0, 'C': 0, 'D': 4} I want to generate a list like this - [{'A': 1, 'B': 0, 'C': 0, 'D': 4}, {'A': 0, 'B': 1, 'C': 0, 'D': 4}, {'A': 0, 'B': 0, 'C': 1, 'D': 4}, {'A': 0, 'B': 0, 'C': 0, 'D': 5}] What is the most pythonic way to do this?
You can use list comprehension and dictionary comprehension together, like this d = {'A': 0, 'B': 0, 'C': 0, 'D': 4} print [{key1: d[key1] + (key1 == key) for key1 in d} for key in d] Output [{'A': 1, 'B': 0, 'C': 0, 'D': 4}, {'A': 0, 'B': 0, 'C': 1, 'D': 4}, {'A': 0, 'B': 1, 'C': 0, 'D': 4}, {'A': 0, 'B': 0, 'C': 0, 'D': 5}] The idea is to generate a new dictionary for each key, and when the key matches the key of the dictionary being constructed with dictionary comprehension, then add 1 to it. (key1 == key) will evaluate to 1 only when both the keys match, otherwise it will be zero.