permuting over nested dicts?
Anand
anandology at gmail.com
Thu Nov 1 05:47:59 EDT 2007
On Nov 1, 2:12 pm, Anand <anandol... at gmail.com> wrote:
> On Oct 31, 10:21 pm, Christian Meesters <meest... at uni-mainz.de> wrote:
>
>
>
> > Hoi,
>
> > I have the following data structure (of variable size actually, to make
> > things simple, just that one):
> > d = {'a': {'x':[1,2,3], 'y':[4,5,6]},
> > 'b': {'x':[7,8,9], 'y':[10,11,12]}}
> > This can be read as a dict of possibilities: The entities 'a' and 'b' have
> > the parameters 'x' and 'y', each. And d['a']['x'] can be either 1 or 2 or
> > 3. Does anybody know a convenient (and fast) way to permute over all
> > possible nested dicts like
> > {'a': {'x':1, 'y':4},
> > 'b': {'x':7, 'y':10}}
> > and
> > {'a': {'x':2, 'y':4},
> > 'b': {'x':7, 'y':10}}
> > and so forth?
>
> > Any link or snippet is appreciated.
>
> This code works for dictionaries of any nested level.
>
> def combine(key, value, permutations):
> """Adds key-value pair to every dictionary in the permutations.
> If value is a list, then every key-element pair is added to every
> permutation.
> >>> list(combine('a', 1, [{}]))
> [{'a': 1}]
> >>> list(combine('a', [1, 2], [{}]))
> [{'a': 1}, {'a': 2}]
> >>> list(combine('a', 1, [{'b': 1}, {'b': 2}]))
> [{'a': 1, 'b': 1}, {'a': 1, 'b': 2}]
> >>> list(combine('a', [1, 2], [{'b': 1}, {'b': 2}]))
> [{'a': 1, 'b': 1}, {'a': 2, 'b': 1}, {'a': 1, 'b': 2}, {'a':
> 2, 'b': 2}]
> """
> for p in permutations:
> if isinstance(value, list):
> for v in value:
> q = p.copy()
> q[key] = v
> yield q
> else:
> p[key] = value
> yield p
>
> def permute(d):
> """
> >>> list(permute({'x': [1, 2, 3]}))
> [{'x': 1}, {'x': 2}, {'x': 3}]
> >>> list(permute({'a': [1, 2], 'b': [3, 4]}))
> [{'a': 1, 'b': 3}, {'a': 2, 'b': 3}, {'a': 1, 'b': 4}, {'a': 2,
> 'b': 4}]
> >>> list(permute({'a': {'x': [1, 2]}, 'b': [3, 4]}))
> [{'a': {'x': 1}, 'b': 3}, {'a': {'x': 2}, 'b': 3}, {'a': {'x': 1},
> 'b': 4}, {'a': {'x': 2}, 'b': 4}]
> """
> if not d:
> return [{}]
> else:
> k, v = d.popitem()
> if isinstance(v, dict):
> v = list(permute(v))
> return combine(k, v, permute(d))
better solution:
def permute(d):
def newdict(d, k, v):
d = d.copy()
d[k] = v
return d
permutations = [{}]
for key, value in d.items():
if isinstance(value, dict):
value = list(permute(value))
elif not isinstance(value, list):
value = [value]
permutations = [newdict(p, key, v) for p in permutations for v
in value]
return permutations
More information about the Python-list
mailing list