Reputation: 41
I want to take a nested dictionary and reverse the values for example
input = { "a" : { "x": 2, "y": 3 },
"b" : { "x": 5, "z": 7 } }
output = {'y': {'a': 3},
'x': {'a': 2, 'b': 5},
'z': {'b': 7} }
what I have:
def reverse_nest_dicts(nested_dict):
reverse_nest_dict = {}
for k, v in nested_dict:
for k2, v2 in nested_dict.values():
reverse_nest_dict[k2][k] = v2
return reverse_nest_dict
Upvotes: 4
Views: 1864
Reputation: 1469
Use NestedDict
. First install ndicts
pip install ndicts
Then
from ndicts.ndicts import NestedDict
input_dict = {"a": { "x": 2, "y": 3 }, "b": { "x": 5, "z": 7 }}
nd = NestedDict(input_dict)
reversed_nd = NestedDict()
for key, value in nd.items():
reversed_key = tuple(reversed(key))
reversed_nd[reversed_key] = value
Finally
>>> reversed_nd.to_dict()
{'x': {'a': 2, 'b': 5}, 'y': {'a': 3}, 'z': {'b': 7}}
Upvotes: 0
Reputation: 1801
If the dictionary is too large, check https://stackoverflow.com/a/47151034/676214
If you want just access reverse nested dictionaries, Save memory if the dictionary is too large to reverse.
class mdict2(dict):
def __init__(self, parent, key1):
self.parent = parent
self.key1 = key1
def __getitem__(self, key2):
return self.parent.mirror[key2][self.key1]
class mdict(dict):
def __init__(self, mirror):
self.mirror = mirror
def __getitem__(self, key):
return mdict2(self, key)
d0 = {
'Bob' : {'item1':3, 'item2':8, 'item3':6},
'Jim' : {'item1':6, 'item4':7},
'Amy' : {'item1':6,'item2':5,'item3':9,'item4':2}
}
d1 = mdict(d0)
d0['Amy']['item1'] == d1['item1']['Amy']
# True
Upvotes: 0
Reputation: 226486
The dictionary items() and setdefault() methods make short work of this kind of problem:
>>> input = { "a" : { "x": 2, "y": 3 },
"b" : { "x": 5, "z": 7 } }
>>> result = {}
>>> for k1, subdict in input.items():
for k2, v in subdict.items():
result.setdefault(k2, {})[k1] = v
>>> result
{'y': {'a': 3}, 'x': {'a': 2, 'b': 5}, 'z': {'b': 7}}
In Python 2, you can get a minor speed boost by using iteritems() instead of items().
Likewise, the use of collections.defaultdict(dict) can be a little faster than using setdefault. Of course, that will return a defaultdict instead of a dict as specified in your question.
Upvotes: 1
Reputation: 527043
for k2, v2 in nested_dict.values():
should be
for k2, v2 in v.items():
(Also note that if you're using Python 2.x, it may be more efficient to use .iteritems()
instead of .items()
.)
You also need to make sure the sub-dictionaries are initialized - you can do this by either using defaultdict
...
from collections import defaultdict
reverse_nest_dict = defaultdict(dict)
...or by using setdefault
:
reverse_nest_dict.setdefault(k2, {})[k] = v2
Upvotes: 2
Reputation: 19631
Your function has three different errors. The following is what you are after:
def reverse_nest_dicts(nested_dict):
reverse_nest_dict = {}
for k, v in nested_dict.iteritems():
for k2, v2 in v.iteritems():
try:
reverse_nest_dict[k2][k] = v2
except KeyError:
reverse_nest_dict[k2] = { k : v2 }
return reverse_nest_dict
The errors are:
1st for loop: using the dictionary as loop sequence will result in keys only, you want (key,value) so need to use items() or iteritems()
2nd for loop: the loop sequence should be the nested dictionary, not the outer dictionary
you need to initialise the reverse_nest_dict values to inner dictionaries before you try to access them.
Upvotes: 1