1

I have 3 tuples:

o = (0, 1)
n = ((1, 2), (1,))
c = ((30, 70), (20,))

that I want to put in a nested dictionary. The desired output is:

{'0':{'1':30, '2':70}, '1':{'1':20}}

I tried the following:

for x in enumerate(o):
    graph[str(o[x])] = {}
    for y in enumerate(n):
        for z in enumerate(y):
            graph[str(o[x])][n[x][z]] = c[x][z]

Which does not work, I am not sure how to proceed.

Bee
  • 11
  • 4

1 Answers1

0

One problem is arising from the fact that (1) and (20) are not tuples (as pointed out by Ilja Everilä in the comments). Since they are actually of type int, you can not iterate over them or use [] to index.

First a note about enumerate(), which you were using incorrectly. This function returns a tuple of (index, value). More info here.

If changing the source data is not an option, you can modify your code a little to get the desired result. Loop over the tuples as before, but use isinstance to check if the element is an int.

graph = {}
for i, x in enumerate(o):
    graph[x] = {}
    if isinstance(n[i], int):
        graph[x][n[i]] = c[i]
    else:
        for j in range(len(n[i])):
            graph[x][n[i][j]] = c[i][j]
print graph
#{0: {1: 30, 2: 70}, 1: {1: 20}}

This else block of this code can be simplified further, using zip():

graph = {}
for i, x in enumerate(o):
    graph[x] = {}
    if isinstance(n[i], int):
        graph[x][n[i]] = c[i]
    else:
        for y, z in zip(n[i], c[i]):
            graph[x][y] = z
print graph
#{0: {1: 30, 2: 70}, 1: {1: 20}}

However, the better solution is to change the source data n and c to contain only tuples:

def make_tuple(x):
    return x if isinstance(x, tuple) else (x, )

new_n = map(make_tuple, n)
new_c = map(make_tuple, c)

Then the code above no longer needs the isinstance() check, and can be simplified to:

graph = {}
for i, x in enumerate(o):
    graph[x] = {}
    for y, z in zip(new_n[i], new_c[i]):
        graph[x][y] = z
print graph
#{0: {1: 30, 2: 70}, 1: {1: 20}}

We can simplify further into:

graph = {}
for ko, N, C in zip(o, new_n, new_c):
    graph[ko] = {}
    for kn, vc in zip(N, C):
        graph[ko][kn] = vc
print graph
#{0: {1: 30, 2: 70}, 1: {1: 20}}

Or if to the compact one liner (direct translation of the code block above to dict comprehension):

graph = {ko: {kn:vc for kn, vc in zip(N, C)} for ko, N, C in zip(o, new_n, new_c)}
print graph
#{0: {1: 30, 2: 70}, 1: {1: 20}}
pault
  • 41,343
  • 15
  • 107
  • 149
  • @Bee, based on your latest comment I see that much of this is not applicable to your problem. Does this make sense to you or would you like further clarification? – pault Feb 02 '18 at 20:06
  • Yes, everything is clear now, thank you so much for your help! – Bee Feb 02 '18 at 20:08