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.
Related
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']}}
I have a list of tuples
data = [('2015-10-08', '2016-07-17'), ('Alex', 'Jerry'), (5, 6)]
And I have a list, this list contains column headings.
title = [Date , Name, Age]
With this list and list of tuples I want a dictionary of dictionaries
This is the expected output
output = {'1' : {'Date': '2015-10-08', 'Name': 'Alex', 'Age': 5},
'2' : {'Date': '2016-07-17', 'Name': 'Jerry', 'Age': 6}}
I tried
output = {}
for i in range(len(title)):
output[i+1] = {title[i]: ",".join(data[i])}
print (output)
I am getting
{1: {'Date': '2015-10-08','2016-07-17'}, 2: {'Name': 'Alex','Jerry'}, 3: {'Age': 5,6}}
You could simply use loops to build easy to read code. But the Pythonic way would be to use comprehensions:
result = {str(i + 1): {t: data[j][i] for j, t in enumerate(title)}
for i in range(len(data[0]))}
It gives as expected:
{'1': {'Age': 5, 'Date': '2015-10-08', 'Name': 'Alex'},
'2': {'Age': 6, 'Date': '2016-07-17', 'Name': 'Jerry'}}
I have a list like this:
list = ['John', 18, 'Spain', 'Adam', 12, 'Hungary', 'Eve', 50, 'Greece', ...]
How can I make a list of dictionaries from it?
The expected result:
[{'name':'John', 'age':18, 'country':'Spain'},
{'name':'Adam', 'age':12, 'country':'Hungary'},
{'name':'Eve', 'age':50, 'country':'Greece'},
...]
You could use zip with different slicing of your values
values[::3] iterates 1 over 3, so only names
values[1::3] iterates 1 over 3 starting at index 1, so only ages
values[2::3] iterates 1 over 3 starting at index 2, so only countries
values = ['John', 18, 'Spain', 'Adam', 12, 'Hungary', 'Eve', 50, 'Greece']
list2 = []
for name, age, country in zip(values[::3], values[1::3], values[2::3]):
list2.append({'name': name, 'age': age, 'country': country})
print(list2)
You can also use dict+zip to build the dict with keys+values
list2 = [
dict(zip(['name', 'age', 'country'], vals))
for vals in zip(values[::3], values[1::3], values[2::3])
]
You need to loop over the list in groups of 3 elements, and append one dictionary each time, not three separate dictionaries.
for i in range(0, len(list), 3):
list2.append({
'name': list[i],
'age': list[i+1],
'country': list[i+2]
})
Also, you shouldn't use list as a variable name, it conflicts with the built-in function with that name.
If you know zip() and that it loops over iterators in parallel, it is interesting to know that it can loop over on a single iterator in parallel, practically slicing the input into tuples:
lista = ['John', 18, 'Spain', 'Adam', 12, 'Hungary', 'Eve', 50, 'Greece']
it = iter(lista)
[adat for adat in zip(it,it,it)]
produces
[('John', 18, 'Spain'), ('Adam', 12, 'Hungary'), ('Eve', 50, 'Greece')]
and then for the dicts you can either index the elements as adat[0], etc. or have Python to assign them to a tuple of variables:
lista = ['John', 18, 'Spain', 'Adam', 12, 'Hungary', 'Eve', 50, 'Greece']
it = iter(lista)
[{'name':name,'age':age,'country':country} for (name,age,country) in zip(it,it,it)]
will display
[{'name': 'John', 'age': 18, 'country': 'Spain'}, {'name': 'Adam', 'age': 12, 'country': 'Hungary'}, {'name': 'Eve', 'age': 50, 'country': 'Greece'}]
Side note: list() is a built-in function, so I renamed the variable to lista, based on adat :-)
(Side note2: zip() consumes the iterator, so it has to be re-created if you try both of these snippets together)
Simple, readable way:
lst = ['John', 18, 'Spain', 'Adam', 12, 'Hungary', 'Eve', 50, 'Greece']
ans = []
for i in range(0,len(lst),3):
ans.append({'name':lst[i], 'age':lst[i+1], 'country':lst[i+2]})
print(ans) #prints [{'name': 'John', 'age': 18, 'country': 'Spain'}, {'name': 'Adam', 'age': 12, 'country': 'Hungary'}, {'name': 'Eve', 'age': 50, 'country': 'Greece'}]
A quick and dirty way to do it is like this:
list_1 = ['John', 18, 'Spain', 'Adam', 12, 'Hungary', 'Eve', 50, 'Greece']
list_2 = []
for i in range(0, len(list_1), 3):
list_2.append({'name': list_1[i], 'age': list_1[i + 1], 'country': list_1[i + 2]})
here is my take on the problem
list_ = ['John', 18, 'Spain', 'Adam', 12, 'Hungary', 'Eve', 50, 'Greece']
result = []
for index, item in enumerate(list_):
try:
int(item)
dictionary = dict()
dictionary['name'] = list_[index - 1]
dictionary['age'] = item
dictionary['country'] = list_[index + 1]
result.append(dictionary)
except ValueError:
pass
print(result)
its pretty simple enumerate gives another variable which is list index, then I try to make item in list integer and that wont happen with those strings so it will throw ValueError and pass and continue untile it finds an int then it will create a dictionary and add neccessary items to the it and then add the dictionary to the list (also do not use list as variable because its python reserved? keyword?)
You can loop over the list over every three steps. An example to help get you started is:
>>> for i in range(0, 12, 3): # 0 = start value, 12 = stop value, 3 = step
... print(i)
...
0
3
6
9
>>>
Similarly you can do:
data_list = ['John', 18, 'Spain', 'Adam', 12, 'Hungary', 'Eve', 50, 'Greece'...]
data_dicts = []
for i in range(0, len(data_list), 3):
data_dicts.append(
{'name': data_list[i], # The first element in a group of 3 (the name)
'age': data_list[i + 1], # The second element in the group (the age)
'country': data_list[i + 2] # The last element in the group (the country)
}
)
Also, you shouldn't name any variable list because it will override the built in python list class
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}]}
My data is a dict of dicts like this (but with a lot more fields and names):
{'Jack': {'age': 15, 'location': 'UK'},
'Jill': {'age': 23, 'location': 'US'}}
I want to export it to a spreadsheet like this:
Name Age Location
Jack 15 UK
Jill 23 US
But apparently csv.DictWriter wants to see a list of dicts like this:
[{'name': 'Jack', 'age': 15, 'location': 'UK'},
{'name': 'Jill', 'age': 23, 'location': 'US'}]
What's the simplest way to get my dict of dicts into a CSV file?
I suppose the entries should be in alphabetical name order, too, but that's easy enough to do in the spreadsheet software.
mydict = {'Jack': {'age': 15, 'location': 'UK'},
'Jill': {'age': 23, 'location': 'US'}}
datalist = []
for name in mydict:
data = mydict[name]
data['name'] = name
datalist.append(data)
And datalist will hold the desired result. Notes:
This also modifies mydict (adding the 'name' key to each datum). You probably don't mind about that. It's a bit more efficient than the alternative (copying).
It's not the most flashy one-line-way-to-do-it, but it's very readable, which IMHO is more important
You can use list-comprehension to get your new list of dicts:
>>> [dict(zip(['name'] + attrs.keys(), [name] + attrs.values())) \
for name, attrs in d.iteritems()]
[{'age': 23, 'location': 'US', 'name': 'Jill'},
{'age': 15, 'location': 'UK', 'name': 'Jack'}]
EDIT: d is your dict:
>>> d
{'Jack': {'age': 15, 'location': 'UK'}, 'Jill': {'age': 23, 'location': 'US'}}