user13074756
user13074756

Reputation: 413

Create a nested Dictionary with two dictionaries

I have a nested list called multi:

[[14, 77766 ,[2, 2]],
 [15, 77766,  [1, 2]],
 [70, 88866, [1, 5]],
 [71, 88866,[2, 5]],
 [72, 88866, [5, 5]],
 [73, 88866, [4, 5]],
 [74, 88866, [3, 5]],
 [79, 99966, [1, 2]],
 [80, 99966, [2, 2]]] 

I need my output to be:

{77766:  {14:2 ,15:1} , 88866: {70:1, 71:2, 72:5, 73:4, 74:3}, 99966: {79:1, 80:2}}

I have written codes that produced the below two dictionaries. How do I combine them to achieve the output I want?

a = {77766: [14, 15], 88866: [70, 71, 72, 73, 74], 99966: [79, 80]}
b = {14: 2, 15: 1, 70: 1, 71: 2, 72: 5, 73: 4, 74: 3, 79: 1, 80: 2}

Upvotes: 2

Views: 3401

Answers (4)

T. Pieper
T. Pieper

Reputation: 36

For this problem defauldict(dict) is really handy. By passing in dict you define an empty dictionary as the default value. That means: If you try to access a key that doesn't exist yet an empty dictionary is created for this key.

res = defaultdict(dict)
for inner_key, key, inner_value in multi:
    res[key].update({inner_key: inner_value[0]}) 

Note that you receive a defaultdict instead of a regular dictionary. If you need the later for your use-case, you can make use of:

res = {}
for inner_key, key, inner_value in multi:
    if key not in res:
        res[key] = {}
    res[key].update({inner_key: inner_value[0]})

Upvotes: 0

Ch3steR
Ch3steR

Reputation: 20689

You can use defaultdict here. multi need not be sorted.

from collections import defaultdict
out=defaultdict(dict)
for v,k,vs in multi:
    out[k]={**out[k],**{v:vs[0]}}

Output

defaultdict(dict,
            {77766: {14: 2, 15: 1},
             88866: {70: 1, 71: 2, 72: 5, 73: 4, 74: 3},
             99966: {79: 1, 80: 2}})

EDIT:

Sorting the inner dictionaries.

out={k:dict(sorted(v.items(),key=lambda x:x[1])) for k,v in out.items()}

Output:

{77766: {15: 1, 14: 2},
 88866: {70: 1, 71: 2, 74: 3, 73: 4, 72: 5},
 99966: {79: 1, 80: 2}}

Upvotes: 2

Boseong Choi
Boseong Choi

Reputation: 2596

1. Merge your dictionaries

a = {77766: [14, 15], 88866: [70, 71, 72, 73, 74], 99966: [79, 80]}
b = {14: 2, 15: 1, 70: 1, 71: 2, 72: 5, 73: 4, 74: 3, 79: 1, 80: 2}

c = {
    k: {
        i: b[i]
        for i in v
    }
    for k, v in a.items()
}
print(c)

output:

{77766: {14: 2, 15: 1}, 88866: {70: 1, 71: 2, 72: 5, 73: 4, 74: 3}, 99966: {79: 1, 80: 2}}

2. Build result dictionary at directly from original dictionary

data = [
    [14, 77766, [2, 2]],
    [15, 77766, [1, 2]],
    [70, 88866, [1, 5]],
    [71, 88866, [2, 5]],
    [72, 88866, [5, 5]],
    [73, 88866, [4, 5]],
    [74, 88866, [3, 5]],
    [79, 99966, [1, 2]],
    [80, 99966, [2, 2]],
]

c = {}
for key, id_, (value, _) in data:
    c.setdefault(id_, {})[key] = value
print(c)

output: same with above

Upvotes: 1

AKX
AKX

Reputation: 169388

Assuming your input list is sorted by the second column, you can use itertools.groupby:

import itertools

multi = [
    [14, 77766, [2, 2]],
    [15, 77766, [1, 2]],
    [70, 88866, [1, 5]],
    [71, 88866, [2, 5]],
    [72, 88866, [5, 5]],
    [73, 88866, [4, 5]],
    [74, 88866, [3, 5]],
    [79, 99966, [1, 2]],
    [80, 99966, [2, 2]],
]

nested = {
    key: {l[0]: l[2][0] for l in lines}
    for key, lines in itertools.groupby(multi, lambda p: p[1])
}

outputs

{77766: {14: 2, 15: 1},
 88866: {70: 1, 71: 2, 72: 5, 73: 4, 74: 3},
 99966: {79: 1, 80: 2}}

Upvotes: 2

Related Questions