Assuming that I have a nested dictionary, that is extracted from pickle file, that contains various levels, I would like to get the value by giving only the last key. Keys are unique considering own 'branch'.
The main problem is that I have multiple keys and levels:
dict = {
'A': {
'X': {
1: [...],
2: [...]
},
'Y': {
3: [...],
4: [...]
}
}
'B': {
'G': {
'H': {
'Z': [...]
}
}
}
'C': [...]
}
How can I do that?
a simple solution would be a recusrive function that even works for nested, nested dictionarys
outer_dict = {'outer': {'inner': 10, 'even_inner': {'innerst': 25}}}
and the function:
def get_val(search_dict, key):
""" recursive searching the dict """
for elem in search_dict:
if elem == key:
return search_dict[elem]
if isinstance(search_dict[elem], dict):
retval = get_val(search_dict[elem], key)
if retval is not None:
return retval
value = get_val(outer_dict, 'innerst')
print(value)
>> 25
Problems:
if the key is not unique you will get only the first match. You will need a list to fill a values into if the key can be there more than once.
Please provide a example next time!
Related
I'm trying to build up an dictionary based on a list with a dynamic size.
parts = [['Sect', 'H1'],
['Sect', 'P'],
['Sect', 'P[2]'],
['Sect[2]', 'Sect', 'H2']]
Should result in such a dictionary like:
{
"Sect": {
"H1": {
},
"P": {
},
"P[2]": {
},
},
"Sect[2]": {
"Sect": {
"H2": {
}
}
}
}
I can't get it. Any idea how to turn a list of dynamic size into a tree structured dictionary?
My approach so far:
for i, part in enumerate(parts):
if i == 0:
if part not in result:
result[part] = dict()
if i == 1:
if part not in result[parts[i-1]]:
result[parts[i-1]][part] = dict()
if i == 2:
if part not in result[parts[i-2]][parts[i-1]]:
result[parts[i-2]][parts[i-1]][part] = dict()
...
But this isn't a dynamic approach so far.
Similar to quamrana's answer, but a bit terser with dict.setdefault.
d = {}
for p in parts:
inner = d
for k in p:
inner = inner.setdefault(k, {})
print(d) # {'Sect[2]': {'Sect': {'H2': {}}}, 'Sect': {'P[2]': {}, 'P': {}, 'H1': {}}}
The answer is iteration. You can iterate over a list of lists. And for each list you can iterate to produce hierarchical dicts.
parts = [['Sect', 'H1'],
['Sect', 'P'],
['Sect', 'P[2]'],
['Sect[2]', 'Sect', 'H2']]
data = {}
for part in parts:
d = data # refer to a current dict
for key in part:
new_dict = d[key] if key in d else {}
d[key] = new_dict
d = new_dict # recurse down the nested dicts
print(data)
I'm trying to dynamically create a database without hard coding all of the API response values for columns and rows so I want to learn how to automatically parse through JSON and put all the keys/values in a variable so I can sort through and put them in the db.
Lets say I had some JSON like this:
(modified snippet from destiny 2 API response indented by 5)
{
"Response": {
"profile": {
"data": {
"userInfo": {
"crossSaveOverride": 1,
"applicableMembershipTypes": [
3,
1
],
"isPublic": true,
"membershipType": 1,
"membershipId": "123",
"displayName": "Name1",
"bungieGlobalDisplayName": "name again",
"bungieGlobalDisplayNameCode": 0000
},
"dateLastPlayed": "2021-6-18T02:33:01Z",
"versionsOwned": 127,
"characterIds": [
"id1",
"id2",
"id3"
],
"seasonHashes": [
3243434344,
3423434244,
3432342443,
3434243244
],
"currentSeasonHash": 3434243244,
"currentSeasonRewardPowerCap": 1330
},
"privacy": 1
}
},
"ErrorCode": 1,
"ThrottleSeconds": 0,
"ErrorStatus": "Success",
"Message": "Ok",
"MessageData": {}
}
I want to automatically parse through and get all of the key/values minus the error code area so everything under "Response". It would all go into the database for example:
displayName
isPublic
Name1
True
Name2
False
I know how to parse normally or loop through but only to grab values like:
displayName = Response["Response"]["profile"]["data"]["userInfo"]["displayName"]
How does one grab all keys and values and then automatically store in a variable from the lowest level? Also, how would one exclude keys if they are not needed?
EDIT: Adding Clarification
I learned that this JSON response type is a dict and I can use Response.keys() and Response.values() to get the keys and values.
What I am asking is, from Response["Response"], how to get all of the keys and values down to the bottom level and exclude the ones I don't need.
For example if I do:
r = Response["Response"]
for key in r.keys():
print(key)
I'm only going to get profile which is what I don't need.
I would have to do:
r = Response["Response"]["profile"]["data"]["userInfo"]
for key in r.keys():
print(key)
which would return
crossSaveOverride
applicableMembershipTypes
isPublic
membershipType
membershipId
displayName
bungieGlobalDisplayName
bungieGlobalDisplayNameCode
Which is what I need but I do not want to manually define
["Response"]["profile"]["data"]["userInfo"]or similar for every response. I want to grab everything automatically while excluding the items I don't need.
Dmitry Torba over at Get all keys of a nested dictionary posted a function that does what you want.
def recursive_items(dictionary):
for key, value in dictionary.items():
if type(value) is dict:
yield from recursive_items(value)
else:
yield (key, value)
a = {'a': {1: {1: 2, 3: 4}, 2: {5: 6}}}
for key, value in recursive_items(a):
print(key, value)
I have tried this approach, what if there is list type in given dictionary!
CallPretty.py
def JsonPrint(response, response_Keys):
print()
print(response_Keys)
for i in range(len(response_Keys)):
if type(response[response_Keys[i]]) == list:
print()
for j in range(len(response[response_Keys[i]])):
if type(response[response_Keys[i]][j]) == dict:
JsonPrint(response[response_Keys[i]][j], list(response[response_Keys[i]][j].keys()))
elif type(response[response_Keys[i]]) == dict:
JsonPrint(response[response_Keys[i]], list(response[response_Keys[i]].keys()))
else:
print(response_Keys[i], ':')
for j in range(len(response[response_Keys[i]].split('\n'))):
print('\t', response[response_Keys[i]].split('\n')[j])
I have two nested dictionaries (loaded from json) and need to check if the keys in one already exist in the other, and if not add them.
Example json:
eg_dict = {
"A":
{
"A1":
{
"A1a": "bird",
"A1b": true,
"A1c": false
},
"A2":
{
"A2a":
{
"A2a1": "parrot",
"A2a2":
{
"enabled": true
}
}
}
},
"B":
{
"B1":
{
"B1a": "Reptile"
},
"A2":
{
"A2a":
{
"A2a2":
{
"enabled": true
}
}
}
}
}
I need to add A1 and A2a1 to B.
I've tried Check if a nested dictionary is a subset of another nested dictionary but it's not doing quite what I need.
I started trying to pass the parent key through a recursive function, but as I don't know how deep the nesting goes, this seems like a dead end?
def get_all_values(pkey, nested_dictionary):
#I don't think passing p(arent)key to the function gets me anywhere
for key, value in nested_dictionary.items():
if type(value) is dict:
print(key, ":", value)
get_all_values(pkey, value)
else:
print(key, ":", value)
def get_json(file, chartname):
#print(chartname)
with open(file) as file:
file= json.load(file)
b = file['B']
#Can do it if I know the key I want to copy
if 'A1' in file['A'].keys():
b['A1'] = file['A']['A1']
#Trying a function to get all missing keys from A
get_all_values(key=None, file['B'])
b = json.dumps(b)
return b
First time posting on stackoverflow, so help on improving my question welcome too!
A recursive solution to build a dictionary from A and B, where values of A have precedence over values of B:
a_dict = eg_dict['A']
b_dict = eg_dict['B']
print(a_dict)
# {'A1': {'A1a': 'bird', 'A1b': True, 'A1c': False}, 'A2': {'A2a': {'A2a1': 'parrot', 'A2a2': {'enabled': True}}}}
print(b_dict)
# {'B1': {'B1a': 'Reptile'}, 'A2': {'A2a': {'A2a2': {'enabled': True}}}}
def extend_dict(primary_dict, secondary_dict):
result_dict = {}
for k in set(primary_dict.keys()).union(set(secondary_dict.keys())):
if (k in primary_dict.keys() and k in secondary_dict.keys()) and (isinstance(primary_dict[k], dict) and isinstance(secondary_dict[k], dict)):
result_dict.update({k: extend_dict(primary_dict[k], secondary_dict[k])})
elif k in primary_dict.keys():
result_dict.update({k: primary_dict[k]})
elif k in secondary_dict.keys():
result_dict.update({k: secondary_dict[k]})
return result_dict
extended = extend_dict(a_dict, b_dict)
print(extended)
# {'B1': {'B1a': 'Reptile'}, 'A2': {'A2a': {'A2a2': {'enabled': True}, 'A2a1': 'parrot'}}, 'A1': {'A1a': 'bird', 'A1b': True, 'A1c': False}}
If you want to switch the precedence, just switch A and B, such that extended = extend_dict(b_dict, a_dict).
Let me know if this is what you are looking for.
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)
I have dict of dicts in Python, it can be deep, not just 2 levels.
data = {
0: {
1: {
2: "Yes"
},
3: {
4: "No"
}
},
}
I need to get and set the data, but the key is dynamic and is stored in list
key_to_get = [0,1,2]
print(data.get(key_to_get))
Should print Yes
Ideas?
Here is a simple recursive function which solves the problem
def getValue(dict, keys):
if len(keys) == 1:
return dict.get(keys[0])
return getValue(dict.get(keys[0]), keys[1:])
And an iterative approach if you're boring
temp = data
for key in key_to_get:
temp = temp.get(key)
print(temp)