Appending items in a nested python dictionary - python

I have a nested python dictionary in the following format
{"exist":{"name":["a","b"],"country":["US"],"team":["SP","FR"]}, "not_exist":{}}
I want to append the following dictionary to the above one:
{"exist":{"age":[23,43,45],"sports":["football","rugby"]}, "not_exist":{"title":["Mr","Ms"]}}
So that the resulting dictionary looks like
{"exist":{"name":["a","b"],"country":["US"],"team":["SP","FR"],"age":[23,43,45],"sports":["football","rugby"]},
"not_exist":{"title":["Mr","Ms"]}}
I tried with update method, but its not working.

You can also use | operator (for python 3.9+) between dicts:
dct1 = {"exist":{"name":["a","b"],"country":["US"],"team":["SP","FR"]}, "not_exist":{}}
dct2 = {"exist":{"age":[23,43,45],"sports":["football","rugby"]}, "not_exist":{"title":["Mr","Ms"]}}
output = {k: v | dct2[k] for k, v in dct1.items()}
print(output)
# {'exist': {'name': ['a', 'b'], 'country': ['US'], 'team': ['SP', 'FR'], 'age': [23, 43, 45], 'sports': ['football', 'rugby']},
# 'not_exist': {'title': ['Mr', 'Ms']}}
For python with version lower than 3.9, you can use:
for k, v in dct2.items():
dct1[k].update(v)
print(dct1)
Note that this modifies your original dct1.

You can traverse the second dictionary and append all those values to the first one as follows:
d = {"exist":{"name":["a","b"],"country":["US"],"team":["SP","FR"]}, "not_exist":{}}
d1 = {"exist":{"age":[23,43,45],"sports":["football","rugby"]}, "not_exist":{"title":["Mr","Ms"]}}
for i in list(d1["exist"].keys()):
d["exist"][i] = d1["exist"][i]
print(d1)
Output:
{'exist': {'age': [23, 43, 45], 'sports': ['football', 'rugby']}, 'not_exist': {'title': ['Mr', 'Ms']}}

dict1 = {"exist":{"name":["a","b"],"country":["US"],"team":["SP","FR"]}, "not_exist":{}}
dict2 = {"exist":{"age":[23,43,45],"sports":["football","rugby"]}, "not_exist":{"title":["Mr","Ms"]}}
dict1["exist"].update(dict2["exist"])
dict1["not_exist"].update(dict2["not_exist"])
print(dict1)
This simple code snippet did the trick for me?
Output:
{'exist': {'name': ['a', 'b'], 'country': ['US'], 'team': ['SP', 'FR'], 'age': [23, 43, 45], 'sports': ['football', 'rugby']}, 'not_exist': {'title': ['Mr', 'Ms']}}

Related

Add list values to dictionary of lists

I have a dict of lists:
my_dict = {'Name': ['John', 'Peter', 'Greg'], 'Age': [26, 39, 48]}
I want to add new values from a flat list to each key of the dictionary:
new_row = ['Bob', 23]
So the final dictionary would look like this:
{'Name': ['John', 'Peter', 'Greg', 'Bob'], 'Age': [26, 39, 48, 23]}
What's the most efficient and smartest way to do this, preferably without relying on imported modules?
This would work, but is there a better way?
i = 0
for k in my_dict.keys():
my_dict[k].append(new_row[i])
i += 1
You can use append for the values in keys Name and Age since both of them are lists, and lists are mutable
my_dict['Name'].append(new_row[0])
my_dict['Age'].append(new_row[1])
my_dict
Out[27]: {'Name': ['John', 'Peter', 'Greg', 'Bob'], 'Age': [26, 39, 48, 23]}
You can zip the values of the dict with the list.
for l, x in zip(my_dict.values(), new_row):
l.append(x)
You could also use a dictionary comprehension to create a new dict without modifying the original.
new_dict = {k: v + [x] for (k,v), x in zip(my_dict.items(), new_row)}

How to convert a list of keys and a list of value lists to a single list of dictionaries?

I have a list of keys and a list of value lists.
What I need to do is to convert these two lists to a single list with dictionaries.
I have a key list:
keys = ['id','firstname','lastname']
My value list is like:
values = [[23,'abc','gef'],[24,'aabb','ppqq']]
The expected output is:
data = [{'id':23,'firstname':'abc','lastname':'gef'}, {'id':24,'firstname':'aabb','lastname':'ppqq'}]
I will be working with a large list as 'values' list. Is there any efficient 'pythonic' way to do this?
Try a simple list comprehension:
>>> keys = ['id','firstname','lastname']
>>> values = [[23,'abc','gef'],[24,'aabb','ppqq']]
>>> [dict(zip(keys, value)) for value in values]
[{'id': 23, 'firstname': 'abc', 'lastname': 'gef'}, {'id': 24, 'firstname': 'aabb', 'lastname': 'ppqq'}]
a one-liner would be data = [{k:v for k, v in zip(keys, v)} for v in values] which combines a list comp and dict comp
>>> keys =['id','name1','name2']
>>> values = [[23, 'a','g'],[24,'ab','cc']]
>>> data = [{k:v for k, v in zip(keys, v)} for v in values]
>>> data
[{'id': 23, 'name1': 'a', 'name2': 'g'}, {'id': 24, 'name1': 'ab', 'name2': 'cc'}]
Using list comprehension.
zip() is to map the similar index of multiple containers so that they can be used just using as single entity.
keys = ['id','firstname','lastname']
value = [[23, 'abc', 'gef'], [24, 'aabb', 'ppqq']]
data = [{k:v for k,v in zip(keys,v)} for v in value ]
print(data)
O/P:
[{'id': 23, 'firstname': 'abc', 'lastname': 'gef'}, {'id': 24, 'firstname': 'aabb', 'lastname': 'ppqq'}]

Check the values in complex dict of dicts with another dict of dicts and save it a third dictionary

The input dictionary of dictionaries are dict1 and dict2.
dict1 = {company1:[{'age':27,'weight':200,'name':'john'},{'age':23,'weight':180,'name':'peter'}],
company2:[{'age':30,'weight':190,'name':'sam'},{'age':32,'weight':210,'name':'clove'},{'age':21,'weight':170,'name':'steve'}],
company3:[{'age':36,'weight':175,'name':'shaun'},{'age':40,'weight':205,'name':'dany'},{'age':25,'weight':160,'name':'mark'}]
company4:[{'age':36,'weight':155,'name':'lina'},{'age':40,'weight':215,'name':'sammy'},{'age':25,'weight':190,'name':'matt'}]
}
dict2 = {company2:[{'age':30},{'age':45},{'age':52}],
company4:[{'age':43},{'age':67},{'age':22},{'age':34},{'age':42}]
}
I am trying to write a logic where I can check inner key ('age') of each compay key in dict2 exist in same company key dict1, even if one value of inner key 'age' matches with inner key ('age') in dict1 of same company key, then save it to a third dictionary. Please check the below example
Example:
company2:[{'age':30}]
matches with
company2:[{'age':30,'weight':190,'name':'sam'}, ...]
Also I want to save the key:values of dict1 which doesn't appered in dict2 to the dict3, As we can see in the below example company1 key does not apper in dict2.
Example:
company1:[{'age':27,'weight':200,'name':'john'},{'age':23,'weight':180,'name':'peter'}]
and
company3:[{'age':36,'weight':175,'name':'shaun'},{'age':40,'weight':205,'name':'dany'},{'age':25,'weight':160,'name':'mark'}]
Expected Output:
dict3 = {company1:[{'age':27,'weight':200,'name':'john'},{'age':23,'weight':180,'name':'peter'}],
company2:[{'age':30,'weight':190,'name':'sam'},{'age':32,'weight':210,'name':'clove'},{'age':21,'weight':170,'name':'steve'}]
company3:[{'age':36,'weight':175,'name':'shaun'},{'age':40,'weight':205,'name':'dany'},{'age':25,'weight':160,'name':'mark'}]}
pardon my explanation!
This solution might be better done using some other method more succinctly. However, it accomplishes the desired result.
from pprint import pprint
dict3 = dict()
dict1 = {'company1':[{'age':27,'weight':200,'name':'john'},{'age':23,'weight':180,'name':'peter'}],
'company2':[{'age':30,'weight':190,'name':'sam'},{'age':32,'weight':210,'name':'clove'},{'age':21,'weight':170,'name':'steve'}],
'company3':[{'age':36,'weight':175,'name':'shaun'},{'age':40,'weight':205,'name':'dany'},{'age':25,'weight':160,'name':'mark'}],
'company4':[{'age':36,'weight':155,'name':'lina'},{'age':40,'weight':215,'name':'sammy'},{'age':25,'weight':190,'name':'matt'}]
}
dict2 = {'company2':[{'age':30},{'age':45},{'age':52}],
'company4':[{'age':43},{'age':67},{'age':22},{'age':34},{'age':42}]
}
for company, array in dict1.items():
if company not in dict2:
dict3[company] = array
else:
# all the ages for this company in dict1
ages = set(map(lambda x: x['age'], array))
for dictref in dict2[company]:
if dictref['age'] in ages:
dict3[company] = array
break
pprint(dict3)
Output was
{'company1': [{'age': 27, 'name': 'john', 'weight': 200},
{'age': 23, 'name': 'peter', 'weight': 180}],
'company2': [{'age': 30, 'name': 'sam', 'weight': 190},
{'age': 32, 'name': 'clove', 'weight': 210},
{'age': 21, 'name': 'steve', 'weight': 170}],
'company3': [{'age': 36, 'name': 'shaun', 'weight': 175},
{'age': 40, 'name': 'dany', 'weight': 205},
{'age': 25, 'name': 'mark', 'weight': 160}]}

Modify dictionary key

Hi I have a dictionary like below
{
'namelist': [{'name':"John",'age':23,'country':'USA'},
{'name':"Mary",'age':12,'country':'Italy'},
{'name':"Susan",'age':32,'country':'UK'}],
'classteacher':'Jon Smith'
}
I would like to know is it possible to change it to
{
'namelist': [{'name_1':"John",'age_1':23,'country_1':'USA'},
{'name_2':"Mary",'age_2':12,'country_3':'Italy'},
{'name_3':"Susan",'age_3':32,'country_3':'UK'}],
'classteacher':'Jon Smith'
}
By adding _1, _2 .... on every last position of every key
Is it possible? Thank you for your help
You can add the new values in the initial list with changing the key and removing the initial values yourdict[j+'_'+str(num)] = yourdict.pop(j)
keys() returns all the keys of a dict (name, age, country in your case)
a = {'namelist': [{'name':"John",'age':23,'country':'USA'},
{'name':"Mary",'age':12,'country':'Italy'},
{'name':"Susan",'age':32,'country':'UK'}]}
num = 1
for i in a['namelist']:
for j in list(i.keys()):
i[j+'_'+str(num)] = i.pop(j)
num += 1
print(a)
# {'namelist': [
# {'name_1': 'John', 'country_1': 'USA', 'age_1': 23},
# {'name_2': 'Mary', 'country_2': 'Italy', 'age_2': 12},
# {'name_3': 'Susan', 'age_3': 32, 'country_3': 'UK'}]}
Here is my one-line style solution, which works even if you have many keys other than 'namelist':
d = {'namelist': [{'name':"John",'age':23,'country':'USA'},
{'name':"Mary",'age':12,'country':'Italy'},
{'name':"Susan",'age':32,'country':'UK'}],
'classteacher':'Jon Smith'
}
d = {k:[{f'{k2}_{nb}':v2 for k2,v2 in i.items()} for nb,i in enumerate(v,1)] if isinstance(v,list) else v for k,v in d.items()}
print(d)
# {'namelist': [{'name_1': 'John', 'age_1': 23, 'country_1': 'USA'},
# {'name_2': 'Mary', 'age_2': 12, 'country_2': 'Italy'},
# {'name_3': 'Susan', 'age_3': 32, 'country_3': 'UK'}]},
# 'classteacher': 'Jon Smith'
# }
However as Aran-Fey said, this is not really readable and very difficult to maintain. So I also suggest you the solution with nested for loops:
d1 = {'namelist': [{'name':"John",'age':23,'country':'USA'},
{'name':"Mary",'age':12,'country':'Italy'},
{'name':"Susan",'age':32,'country':'UK'}],
'classteacher':'Jon Smith'}
for k1,v1 in d1.items():
if isinstance(v1,list):
for nb,d2 in enumerate(v1,1):
for k2 in list(d2):
d2[f'{k2}_{nb}'] = d2.pop(k2)
print(d1)
# {'namelist': [{'name_1': 'John', 'age_1': 23, 'country_1': 'USA'},
# {'name_2': 'Mary', 'age_2': 12, 'country_2': 'Italy'},
# {'name_3': 'Susan', 'age_3': 32, 'country_3': 'UK'}]},
# 'classteacher': 'Jon Smith'
# }
Using enumerate
Ex:
d = {'namelist': [{'name':"John",'age':23,'country':'USA'},
{'name':"Mary",'age':12,'country':'Italy'},
{'name':"Susan",'age':32,'country':'UK'}]}
d["namelist"] = [{k+"_"+str(i): v for k,v in value.items()} for i , value in enumerate(d["namelist"], 1)]
print(d)
Output:
{'namelist': [{'age_1': 23, 'country_1': 'USA', 'name_1': 'John'},
{'age_2': 12, 'country_2': 'Italy', 'name_2': 'Mary'},
{'age_3': 32, 'country_3': 'UK', 'name_3': 'Susan'}]}
You will have to create new key, with value correspond to old key. You can achieve this easily in one line using dict.pop
I will assume you want to add index of the row into field name. For other fields or modified them in other ways, you can do similarly.
for index, row in enumerate(a['namelist']):
row['name_%d' % index] = row.pop('name')
Output:
{'namelist': [{'age': 23, 'country': 'USA', 'name_0': 'John'},
{'age': 12, 'country': 'Italy', 'name_1': 'Mary'},
{'age': 32, 'country': 'UK', 'name_2': 'Susan'}]}
You can use dict and list comprehensions:
d = {'namelist': [{'name': "John", 'age': 23, 'country': 'USA'},
{'name': "Mary", 'age': 12, 'country': 'Italy'},
{'name': "Susan", 'age': 32, 'country': 'UK'}]}
d = {k: [{'_'.join((n, str(i))): v for n, v in s.items()} for i, s in enumerate(l, 1)] for k, l in d.items()}
d would become:
{'namelist': [{'name_1': 'John', 'age_1': 23, 'country_1': 'USA'}, {'name_2': 'Mary', 'age_2': 12, 'country_2': 'Italy'}, {'name_3': 'Susan', 'age_3': 32, 'country_3': 'UK'}]}
Use dictionary comprehension:
mydictionary['namelist'] = [dict((key + '_' + str(i), value) for key,value in mydictionary['namelist'][i-1].items()) for i in [1, 2, 3]]
for i, dct in enumerate(inp['namelist'], 1):
for key, value in list(dct.items()): # take a copy since we are modifying the dct
del dct[key] # delete old pair
dct[key+'_'+str(i)] = value # new key format
This would be in place. You are not using extra memory. Iterating over each value inside the dict and then deleting the old key-value pair and adding the it with a change in the key name.

Python json add multiple keys and iterate

I am looking to convert a dataframe to json, this is the code I currently have:
my_frame = pd.DataFrame(
{'Age':[30, 31],
'Eye':['blue', 'brown'],
'Gender': ['male', 'female']})
my_frame = my_frame.to_json(orient='records')
my_frame
Result:
'[{"Age":30,"Eye":"blue","Gender":"male"},{"Age":31,"Eye":"brown","Gender":"female"}]'
I want to add keys to the json object and add the key info over the entire data that was converted from the dataframe.
add_keys = {'id': 101,
'loc': 'NY',
}
add_keys['info'] = my_frame
add_keys
Result:
{'id': 101,
'info': '[{"Age":30,"Eye":"blue","Gender":"male"},
{"Age":31,"Eye":"brown","Gender":"female"}]',
'loc': 'NY'}
I want to print each of the two records within info, however when I run this iterative code it outputs each character of the string rather than the entire record. I believe this may be an issue from how I am adding the keys.
for item in add_keys['info']:
print(item)
Any help greatly appreciated!
It is better to use pandas inbuilt functionality here. So, this is what you need: add_keys['info'] = my_frame.T.to_dict().values()
Here is the whole code:
>>> my_frame = pd.DataFrame(
... {'Age':[30, 31],
... 'Eye':['blue', 'brown'],
... 'Gender': ['male', 'female']})
>>> my_frame
Age Eye Gender
0 30 blue male
1 31 brown female
>>> add_keys = {'id': 101,
... 'loc': 'NY',
... }
>>> add_keys
{'loc': 'NY', 'id': 101}
>>> add_keys['info'] = my_frame.T.to_dict().values()
>>> add_keys
{'info': [{'Gender': 'male', 'Age': 30L, 'Eye': 'blue'}, {'Gender': 'female', 'Age': 31L, 'Eye': 'brown'}], 'loc': 'NY', 'id': 101}
>>> for item in add_keys['info']:
... print(item)
...
{'Gender': 'male', 'Age': 30L, 'Eye': 'blue'}
{'Gender': 'female', 'Age': 31L, 'Eye': 'brown'}
>>>
When you are using to_json(), pandas is generating a string containing the JSON representation of the dataframe.
If you want to retain the structure of your records in order to manipulate them, use
my_frame = my_frame.to_dict(orient='records')
Then after adding keys, if you want to serialize your data, you can do
json.dumps(add_keys)

Categories