3

Let's say I have the following two dictionaries:

D1={'a':['a2','a3'], 'b':['b5','b7'], 'c':['c4']}
D2={'a':2, 'b':2, 'c':5}

I would like to restructure them so that the values of D2 are the keys that nest the items of D1. Basically I would like the following dictionary:

DictIWant={2:{'a':['a2','a3'], 'b':['b5','b7']}, 5:{'c':['c4']}}

What is the best and most efficient way of doing this? I've stumbled around a bit and have a very clunky way of getting what I want, but I figured it'd be good to learn the correct way of doing this.

So far my first step has been to use reverse D2 as follows:

>>> from collections import defaultdict
>>> D2_Inv = defaultdict(list)
>>> for k, v in D2.items():
...     D2_Inv[v].append(k)
... 
>>> D2_Inv=dict(D2_Inv)
>>> D2_Inv
{2: ['a', 'b'], 5: ['c']}

I'm not that familiar with default dict, but I found out how to do that from this question: How to reverse a dictionary that it has repeated values (python).

Then, I've been doing the following:

>>> NextStep=defaultdict(list)
>>> for Key,Value in D2_Inv.items():
...     for SubValue in Value:
...         New= dict({SubValue: D1[SubValue]})
...         NextStep[Key].append(New)
... 
>>> NextStep=dict(NextStep)
>>> print NextStep
{2: [{'a': ['a2', 'a3']}, {'b': ['b5', 'b7']}], 5: [{'c': ['c4']}]}

Perhaps because I'm not familiar with defaultdict, I'm not sure how to get a dictionary of dictionaries rather than a dictionary of lists of dictionaries.

So then I've been taking this last step to fix that:

>>> DictIWant={}
>>> for k,v in NextStep.items():
...     F=v[0].copy()
...     for i in v[1:]:
...         F.update(i)
...     DictIWant[k]=F
... 
>>> print DictIWant
{2: {'a': ['a2', 'a3'], 'b': ['b5', 'b7']}, 5: {'c': ['c4']}}

I know this is a very clunky way of getting the result I'm looking for. Can someone please offer a more efficient / correct solution?

Community
  • 1
  • 1
AJG519
  • 3,249
  • 10
  • 36
  • 62
  • `NextStep=defaultdict(list)` that says your dict contains list, but you want your dict to contain dict, so `NextStep=defaultdict(dict)`, and then `NextStep[Key].update(New)` instead of `append` – njzk2 Nov 02 '15 at 18:07

1 Answers1

3

You can use a collections.defaultdict(dict) to build this pretty simply.

from collections import defaultdict

D1={'a':['a2','a3'], 'b':['b5','b7'], 'c':['c4']}
D2={'a':2, 'b':2, 'c':5}

D3 = defaultdict(dict)

for k,v in D2.items():
    D3[v].update({k: D1[k]})

print(D3)
# defaultdict(<class 'dict'>, {2: {'b': ['b5', 'b7'], 'a': ['a2', 'a3']}, 5: {'c': ['c4']}})

Since every element in your sub-dicts is key: D1[key] (w.r.t. D2's key,value pairs), you use a defaultdict(dict) to reference a possibly new dictionary at D3[value], then update it with the new element.

You can also use dict.setdefault if you'd rather avoid the defaultdict.

...

D3 = {}
for k,v in D2.items():
    D3.setdefault(v, {}).update({k: D1[k]})  # equivalent
Adam Smith
  • 52,157
  • 12
  • 73
  • 112