Unpack nodes of a dict for each slash in the key - python

I have a dict:
a = {
"group_a/category_a/metric_a": 5,
"group_a/category_a/metric_b": 4,
"group_a/category_b/metric_a": 3,
"group_a/category_b/metric_b": 2,
"group_b/category_a/metric_d": 1
}
I would like to unpack the nodes by creating a nested view, seperated by each slash, where the outcome looks as follows:
b = {
"group_a": {
"category_a": {
"metric_a": 5,
"metric_b": 4
},
"category_b": {
"metric_a": 3,
"metric_b": 2
},
"group_b": {
"category_a": {
"metric_d": 1
}
}
}
How can we go from a to b? I encountered this problem when trying to publish the dict above to Firebase as the nodes group_a/category_a/metric_a is not accepted, whereas a dict that is nested is allowed.

Loop through, split each key into a list of keys, create sub-dictionaries as required...
from pprint import pprint
a = {
"group_a/category_a/metric_a": 5,
"group_a/category_a/metric_b": 4,
"group_a/category_b/metric_a": 3,
"group_a/category_b/metric_b": 2,
"group_b/category_a/metric_d": 1
}
b = {}
for k, v in a.items():
dct = b
keys = k.split("/")
for key in keys[:-1]:
if key not in dct:
dct[key] = {}
dct = dct[key]
dct[keys[-1]] = v
pprint(b)
Gives:
{'group_a': {'category_a': {'metric_a': 5, 'metric_b': 4},
'category_b': {'metric_a': 3, 'metric_b': 2}},
'group_b': {'category_a': {'metric_d': 1}}}

Related

Extract dictionary data which match with other dictionary

I've two dictionaries one original & the other reference. And I want to match reference dict keys with original dict keys and extract all those keys, values from original which are present in reference.
For example
original_dict = {
'a': {
'1': [1, 2, 3, 4, 5]
},
'b': {
'1': {
'A': [1, 2, 3, 4]
}
},
'c': {
'3': [1]
}
}
And a reference dictionary
reference_dict = {
'a': {
'2': [1, 2, 3]
},
'b': {
'1': {
'A': []
}
},
'c': {
'3': []
}
}
And this is the extracted dictionary.
extracted_dict = {
'b': {
'1': {
'A': [1, 2, 3, 4]
}
},
'c': {
'3': [1]
}
}
Here you might have noticed that I don't care about values of reference dict. All I want is the values of original dict.
You can use recursion to accomplish this:
def merge(value_dict, key_dict):
ret = {}
for key, subdict in key_dict.items():
if key in value_dict:
if not isinstance(value_dict[key], dict):
# we found a value so don't keep recursing
ret[key] = value_dict[key]
else:
# found another dict so merge subdicts
merged = merge(value_dict[key], subdict)
if len(merged) > 0:
ret[key] = merged
return ret
merge(original_dict, reference_dict)
I´m not sure if I understand your question 100% but this might be a solution.
we use relevant keys and put them in a list to use them on a .update() dict
new_lst = []
for i in original_dict.keys():
new_lst.append(original_dict[i])
reference_dict.clear()
for i in new_lst:
reference_dict.update(i)
print(reference_dict)

Turn dict with duplicate keys into list containing these keys

I receive a response I have no control over from an API. Using requests response.json() will filter out duplicate keys. So I would need to turn this response into a list where each key is an element in that list: What I get now:
{
"user": {
//...
},
"user": {
//...
},
//...
}
What I need:
{
"users": [
{
"user": {
//...
}
},
{
"user": {
//...
}
},
//...
]
}
This way JSON won't filter out any of the results, and I can loop through users.
Okay, let me have a try by method used in Python json parser allow duplicate keys
All we should do is handle the pairs_list by ourself.
from json import JSONDecoder
def parse_object_pairs(pairs):
return pairs
data = """
{"foo": {"key": 2, "key": 3}, "foo": 4, "foo": 23}
"""
decoder = JSONDecoder(object_pairs_hook=parse_object_pairs)
pairs_list = decoder.decode(data)
# the pairs_list is the real thing which we can use
aggre_key = 's'
def recusive_handle(pairs_list):
dct = {}
for k, v in pairs_list:
if v and isinstance(v, list) and isinstance(v[0], tuple):
v = recusive_handle(v)
if k + aggre_key in dct:
dct[k + aggre_key].append({k: v})
elif k in dct:
first_dict = {k: dct.pop(k)}
dct[k + aggre_key] = [first_dict, {k: v}]
else:
dct[k] = v
return dct
print(recusive_handle(pairs_list))
output:
{'foos': [{'foo': {'keys': [{'key': 2}, {'key': 3}]}}, {'foo': {'bar': 4}}, {'foo': 23}]}

Need Help in Python Dictionary Related Task

Consider a dictionary,
dictionary = {
'AE':{'Applied':4, 'Programming':3 },
'BE':{'Applied':4, 'Programming':2 },
'CE':{'Applied':4, 'Programming':5 },
}
With comprehension in definition, yield the output as,
output = [['AE':'BE':'CE'],
['Applied', 2,4,5],
['Programming', 5,3,2]]
You can use this code:
dictionary = {
'AE':{'Applied':4, 'Programming':3 },
'BE':{'Applied':4, 'Programming':2 },
'CE':{'Applied':4, 'Programming':5 },
}
output = []
dict_keys = list(dictionary.keys())
output.append(dict_keys)
for key in dictionary[dict_keys[0]]:
value = [dictionary[k][key] for k in dict_keys]
value.insert(0, key)
output.append(value)
Output:
output = [['AE', 'BE', 'CE'], ['Applied', 4, 4, 4], ['Programming', 3, 2, 5]]

Subtract dict A from dict B (deep del)?

If I have a deeply nested dict is there a built-in way to subtract/remove list of "paths" (eg: keyA.keyB.key1, keyA.keyC.key2, etc) or a the keys of a second dict from the original dict? Or maybe there is a common module which has functionality like this?
Here's a suggestion:
D = { "keyA": {
"keyB" : {
"keyC" : 42,
"keyD": 13
},
"keyE" : 55
}
}
def remove_path(dictionary, path):
for node in path[:-1]:
dictionary = dictionary[node]
del dictionary[path[-1]]
remove_path(D, ["keyA", "keyB", "keyD"])
print D # prints {'keyA': {'keyB': {'keyC': 42}, 'keyE': 55}}
You'll probably want to introduce some error checking, too.
Just in case the other answers aren't what you're looking for, here's one that subtracts one dictionary from another.
def subtract(a, b):
""" Remove the keys in b from a. """
for k in b:
if k in a:
if isinstance(b[k], dict):
subtract(a[k], b[k])
else:
del a[k]
Another solution:
d = {
'A' : {
'C' : {
'D' : {
'E' : 4,
},
'F' : 5,
},
},
'B' : 2,
}
def DeepDictDel(path, dict):
for key in path.split('.'):
owner = dict
dict = dict[key]
del owner[key]
print d # prints {'A': {'C': {'D': {'E': 4}, 'F': 5}}, 'B': 2}
DeepDictDel('A.C.D', d)
print d # prints {'A': {'C': {'F': 5}}, 'B': 2}

Need to create a layered dict from a flat one

I have a dict, that looks like this:
{
'foo': {
'opt1': 1,
'opt2': 2,
},
'foo/bar': {
'opt3': 3,
'opt4': 4,
},
'foo/bar/baz': {
'opt5': 5,
'opt6': 6,
}
}
And I need to get it to look like:
{
'foo': {
'opt1': 1,
'opt2': 2,
'bar': {
'opt3': 3,
'opt4': 4,
'baz': {
'opt5': 5,
'opt6': 6,
}
}
}
}
I should point out that there can and will be multiple top-level keys ('foo' in this case). I could probably throw something together to get what i need, but I was hoping that there is a solution that's more efficient.
Like this:
def nest(d):
rv = {}
for key, value in d.iteritems():
node = rv
for part in key.split('/'):
node = node.setdefault(part, {})
node.update(value)
return rv
def layer(dict):
for k,v in dict:
if '/' in k:
del dict[k]
subdict = dict.get(k[:k.find('/')],{})
subdict[k[k.find('/')+1:]] = v
layer(subdict)
Got this lib to print your dict in a better way. pprint.
https://docs.python.org/3.2/library/pprint.html

Categories

Resources