简体   繁体   中英

Python: Looping and nested dictionaries

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.

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}}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM