简体   繁体   中英

Printing numbers in a dictionary inside a dictionary by python

I want to print numbers in a dictionary inside a dictionary:

frame = ['frame1', 'frame2', 'frame3', 'frame4', 'frame5', 'frame6']
dx = [12, 34, 55, 66, 78, 65, 56, 234, 876, 999, 345, 945]
pd = ['pd1', 'pd2']

data = {}
dt = {}
k=0
for i in pd :
    dt[i] = []
    for j in frame :
        data[j] = dt
        data[j][i] = dx[k]
        k+=1

For this code it only retains the last values:

{'frame1': {'pd1': 65, 'pd2': 945}, 'frame2': {'pd1': 65, 'pd2': 945}, 'frame3': {'pd1': 65, 'pd2': 945}, 'frame4': {'pd1': 65, 'pd2': 945}, 'frame5': {'pd1': 65, 'pd2': 945}, 'frame6': {'pd1': 65, 'pd2': 945}}

This is the result I want:

{'frame1': {'pd1': 12, 'pd2': 56}, 'frame2': {'pd1': 34, 'pd2': 234}, 'frame3': {'pd1': 55, 'pd2': 876}, 'frame4': {'pd1': 66, 'pd2': 999}, 'frame5': {'pd1': 78, 'pd2': 345}, 'frame6': {'pd1': 65, 'pd2': 945}}

How can I accomplish this?

It looks like there's some shared memory across all the dictionaries.

You can construct the dictionary using a dictionary comprehension:

{f: dict(zip(pd, vals)) for f, vals in zip(frame, zip(dx[:len(dx)//2], dx[len(dx)//2:]))}

This outputs:

{
 'frame1': {'pd1': 12, 'pd2': 56}, 'frame2': {'pd1': 34, 'pd2': 234}, 
 'frame3': {'pd1': 55, 'pd2': 876}, 'frame4': {'pd1': 66, 'pd2': 999}, 
 'frame5': {'pd1': 78, 'pd2': 345}, 'frame6': {'pd1': 65, 'pd2': 945}
}

You can get it from a nested dictionary comperhension, but it is a bit long:

{f: d for f, d in zip(frame, {pd[0]: i, pd[1]: j} for i, j in zip(dx[:len(frame)], dx[len(frame):]))}

A little simplification:

dict(zip(frame, (dict(zip(pd, x)) for x in zip(dx[:len(frame)], dx[len(frame):]))))

Output:

{'frame1': {'pd1': 12, 'pd2': 56},
 'frame2': {'pd1': 34, 'pd2': 234},
 'frame3': {'pd1': 55, 'pd2': 876},
 'frame4': {'pd1': 66, 'pd2': 999},
 'frame5': {'pd1': 78, 'pd2': 345},
 'frame6': {'pd1': 65, 'pd2': 945}}

This should work

data = {}
k=0
for i in pd:
    for j in frame :
        # use setdefault to initialize inner dictionary
        data.setdefault(j, {})[i] = dx[k]
        k+=1
data
{'frame1': {'pd1': 12, 'pd2': 56},
 'frame2': {'pd1': 34, 'pd2': 234},
 'frame3': {'pd1': 55, 'pd2': 876},
 'frame4': {'pd1': 66, 'pd2': 999},
 'frame5': {'pd1': 78, 'pd2': 345},
 'frame6': {'pd1': 65, 'pd2': 945}}

Your issue is that you're resetting dt over every iteration of your outer for-loop. To get your desired output, just do this

for i in pd:
    for j in frame:
        if j not in data:
            data[j] = dict()
        data[j][i] = dx[k]
        k += 1

You can compress this into a list comprehension like this:

data = {f: {p: dx[j * len(frame) + i] for j, p in enumerate(pd)} for i, f in enumerate(frame)}

This compression iterates over frames and, for each item in frames , iterates over pd . For each item in pd , we then add items to a dictionary when we then add to the larger dictionary. The value of dx added to the dictionary is based on the jth entry of pd and the ith entry of frames .

Better variable names help track what is going on. Readability counts vs. one-liner list comprehensions. The original code was inserting the same modified dictionary in each frame.

from pprint import pprint

frames = ['frame1', 'frame2', 'frame3', 'frame4', 'frame5', 'frame6']
dx = [12, 34, 55, 66, 78, 65, 56, 234, 876, 999, 345, 945]
pds = ['pd1', 'pd2']

# Initialize each frame with a *different* empty dictionary
data = {frame:{} for frame in frames}

# Distribute dx across the frames and pds:
idx = iter(dx)
for pd in pds:
    for frame in frames:
        data[frame][pd] = next(idx)

pprint(data)

Output:

{'frame1': {'pd1': 12, 'pd2': 56},
 'frame2': {'pd1': 34, 'pd2': 234},
 'frame3': {'pd1': 55, 'pd2': 876},
 'frame4': {'pd1': 66, 'pd2': 999},
 'frame5': {'pd1': 78, 'pd2': 345},
 'frame6': {'pd1': 65, 'pd2': 945}}

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