John
John

Reputation: 497

Double loop over nested dictionary in Python

I have a nested dictionary in Python like this:

funcs = {1:{-1:{'a': 1, 'b': 2}, 0:{'a': 3, 'b': 4}, 1:{'a': 5, 'b': 6}},
2:{-2:{'a': 7, 'b': 8}, -1:{'a': 9, 'b': 10}, 0:{'a': 11, 'b': 12}, 1:{'a': 13, 'b': 14}, 2:{'a': 15, 'b': 16}}}

It has three levels of nested dictionaries:

I need to run a function g(x,y) over each possible pair of values in the lowest level of the dictionary (so 16x16 operations). Obviously, I can do this by running over all keys in a 6-nested loop, but I was hoping for something more efficient and pythonic.

If the outermost level had only m=1, the resulting matrix would look like:

g(f[1][-1][a], f[1][-1][a]), g(f[1][-1][a], f[1][-1][b]), g(f[1][-1][a], f[1][0][a]), g(f[1][-1][a], f[1][0][b]), g(f[1][-1][a], f[1][1][a]), g(f[1][-1][a], f[1][1][b])
g(f[1][-1][b], f[1][-1][a]), g(f[1][-1][b], f[1][-1][b]), g(f[1][-1][b], f[1][0][a]), g(f[1][-1][b], f[1][0][b]), g(f[1][-1][b], f[1][1][a]), g(f[1][-1][b], f[1][1][b])
g(f[1][0][a], f[1][-1][a]), g(f[1][0][a], f[1][-1][b]), g(f[1][0][a], f[1][0][a]), g(f[1][0][a], f[1][0][b]), g(f[1][0][a], f[1][1][a]), g(f[1][0][a], f[1][1][b])
g(f[1][0][b], f[1][-1][a]), g(f[1][0][b], f[1][-1][b]), g(f[1][0][b], f[1][0][a]), g(f[1][0][b], f[1][0][b]), g(f[1][0][b], f[1][1][a]), g(f[1][0][b], f[1][1][b])
g(f[1][1][a], f[1][-1][a]), g(f[1][1][a], f[1][-1][b]), g(f[1][1][a], f[1][0][a]), g(f[1][1][a], f[1][0][b]), g(f[1][1][a], f[1][1][a]), g(f[1][1][a], f[1][1][b])
g(f[1][1][b], f[1][-1][a]), g(f[1][1][b], f[1][-1][b]), g(f[1][1][b], f[1][0][a]), g(f[1][1][b], f[1][0][b]), g(f[1][1][b], f[1][1][a]), g(f[1][1][b], f[1][1][b])

Upvotes: 0

Views: 162

Answers (2)

Poojan
Poojan

Reputation: 3519

  • I think what you need to use is itertools.product.
  • First get list of all numbers you want to create combinations for. Then using itertools.product generate permutation of numbers.
import itertools
funcs = {1:{-1:{'a': 1, 'b': 2}, 0:{'a': 3, 'b': 4}, 1:{'a': 5, 'b': 6}},
2:{-2:{'a': 7, 'b': 8}, -1:{'a': 9, 'b': 10}, 0:{'a': 11, 'b': 12}, 1:{'a': 13, 'b': 14}, 2:{'a': 15, 'b': 16}}}

l = []
for k,v in funcs.items():
    for k1, v1 in v.items():
        l.extend(v1.values())

print(l)

combi = list(itertools.product(l, repeat=2))

# call fucn of each of combi
for val in combi:
    # print(foo(combi))
    pass

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]

Upvotes: 1

Juan C
Juan C

Reputation: 6132

IIUC, for example if you want to sum the a,b pairs of values and put them on a list:

funcs = {1:{-1:{'a': 1, 'b': 2}, 0:{'a': 3, 'b': 4}, 1:{'a': 5, 'b': 6}},
2:{-2:{'a': 7, 'b': 8}, -1:{'a': 9, 'b': 10}, 0:{'a': 11, 'b': 12},
1:{'a': 13, 'b': 14}, 2:{'a': 15, 'b': 16}}}

def g(funcs):

    return [sum(v2.values()) for v in funcs.values() for v2 in v.values()]

Output:

[3, 7, 11, 15, 19, 23, 27, 31]

Please tell me if you need a more specific application that's not easily generalizable from this.

Upvotes: 0

Related Questions