Related
I am iterating through a list of dictionaries. I need to update the values for one specific key in all the dictionaries and I have the new values stored in a list. The list of new values is ordered so that the 1st new value belongs to a key in the 1st dictionary, 2nd new value to a key in the 2nd dictionary, etc.
My data looks something like this:
dict_list = [{'person':'Tom', 'job':'student'},
{'person':'John', 'job':'teacher'},
{'person':'Mary', 'job':'manager'}]
new_jobs = ['lecturer', 'cook', 'driver']
And I want to transform the list of dictionaries using the list of new jobs according to my description into this:
dict_list = [{'person':'Tom', 'job':'lecturer'},
{'person':'John', 'job':'cook'},
{'person':'Mary', 'job':'driver'}]
As I have a very long list of dictionaries I would like to define a function that would do this automatically but I am struggling how to do it with for loops and zip(), any suggestions?
I tried the for loop below. I guess the following code could work if it was possible to index the dictionaries like this dictionary['job'][i] Unfortunately dictionaries don't work like this as far as I know.
def update_dic_list():
for dictionary in dict_list:
for i in range(len(new_jobs)):
dictionary['job'] = new_jobs[i]
print(dict_list)
The output the code above gave me was this:
[{'person': 'Tom', 'job': 'driver'}, {'person': 'John', 'job': 'teacher'}, {'person': 'Mary', 'job': 'manager'}]
[{'person': 'Tom', 'job': 'driver'}, {'person': 'John', 'job': 'driver'}, {'person': 'Mary', 'job': 'manager'}]
[{'person': 'Tom', 'job': 'driver'}, {'person': 'John', 'job': 'driver'}, {'person': 'Mary', 'job': 'driver'}]
If your new_jobs list has the right job for each corresponding entry in the dict list, you could use zip:
dict_list = [{'person':'Tom', 'job':'student'},
{'person':'John', 'job':'teacher'},
{'person':'Mary', 'job':'manager'}]
new_jobs = ['lecturer', 'cook', 'driver']
for d, j in zip(dict_list, new_jobs):
d['job'] = j
print(dict_list)
prints
[{'person': 'Tom', 'job': 'lecturer'}, {'person': 'John', 'job': 'cook'}, {'person': 'Mary', 'job': 'driver'}]
With your loop, for each dictionary, you're going through the new jobs and updating that same dictionary over and over with each of the jobs until the last one. So by the end of it, they'll all be drivers. Because that's the last one.
You can do
dict_list = [{'person':'Tom', 'job':'student'},
{'person':'John', 'job':'teacher'},
{'person':'Mary', 'job':'manager'}]
new_jobs = ['lecturer', 'cook', 'driver']
def update_dic_list():
for job, _dict in zip(new_jobs, dict_list):
_dict['job'] = job
or
def update_dict_list():
for i, job in enumerate(new_jobs):
dict_list[i]['job'] = job
You only need to remove the inner loop because you are changing dictionary key job more than one time for each of item of outer loop:
def update_dic_list():
i = 0
for dictionary in dict_list:
dictionary['job'] = new_jobs[i]
i += 1
print(dict_list)
Or alternatively you could use enumerate:
def update_dic_list():
for i, dictionary in enumerate(dict_list):
dictionary['job'] = new_jobs[i]
print(dict_list)
Output:
[{'person': 'Tom', 'job': 'lecturer'}, {'person': 'John', 'job': 'cook'}, {'person': 'Mary', 'job': 'driver'}]
I need to sort list of dictionaries according to predefined list of values
I am using this part of code, and it will work fine but l_of_dicts has values which are not in a sort_l(predefined list of values)
l_of_dicts = [{'name':'Max','years':18},{'name':'John','years':25},{'name':'Ana','years':19},{'name':'Melis','years':38},{'name':'Ivana','years':38}]
sort_l = ['Ana','Melis','John','Max','Peter']
res = sorted(l_of_dicts , key = lambda ele: sort_l .index(list(ele.values())[0]))
I get an error :
ValueError: 'Ivana' is not in list
Is it posible to ignore that values? or even better extract them to another list?
The script bellow does the job but looks heavier than it should be. Maybe there's easier way to do it.
Script:
def sort_dict_list(dict_list, sorting_list):
result = []
not_used_values = []
temp = {}
for index, dictionary in enumerate(dict_list):
temp[dictionary['name']] = index
for item in sorting_list:
if item in temp.keys():
result.append(dict_list[temp[item]])
else:
not_used_values.append(item)
return result, not_used_values
You could do some preprocessing to store the ordering of only names in l_of_dicts:
l_of_dicts = [{'name': 'Max', 'years': 18}, {'name': 'John', 'years': 25},
{'name': 'Ana', 'years': 19}, {'name': 'Melis', 'years': 38}]
names_in_dicts = {d['name'] for d in l_of_dicts if 'name' in d}
sort_l = ['Ana', 'Melis', 'Ivana', 'John', 'Max', 'Peter']
sort_order = {name: order for order, name in enumerate(sort_l) if name in
names_in_dicts}
print(sort_order) # {'Ana': 0, 'Melis': 1, 'John': 3, 'Max': 4}
sorted_l_of_dicts = sorted(l_of_dicts, key=lambda d: sort_order[d['name']])
print(sorted_l_of_dicts) # [{'name': 'Ana', 'years': 19}, {'name': 'Melis', 'years': 38}, {'name': 'John', 'years': 25}, {'name': 'Max', 'years': 18}]
I have a list of many dictionaries with only one key value pair like below.
List1 = [{'dept': 'a'}, {'country': 'India'}, {'name':'xyz'}, {'age':32}]
I want to extract name from this list by not using index number but with the dict key.
Can anyone help me out?
Try this:
List1 = [{'dept': 'a'}, {'country': 'India'}, {'name': 'xyz'}, {'age': 32}]
for dic in List1:
name = dic.get('name')
if name is not None: # {'name': ''} which is acceptable.
break
print(name)
output :
xyz
Or use list comprehesion. It always looks better than a loop.
[dic['name'] for dic in List1 if 'name' in dic][0]
I have a dictionary of lists of dictionaries that looks like this:
original_dict = {
1: [{'name': 'Sam'}, {'name': 'Mahmoud'}, {'name': 'Xiao'}],
2: [{'name': 'Olufemi'}, {'name': 'Kim'}, {'name': 'Rafael'}]
}
I know that the names in the lists in this dictionary are all unique. IE: the same name will not appear multiple times in this structure. I want to compile a dictionary of all sub-dictionaries, keyed by their names. I want the result to look like this:
result_dict = {
'Sam': {'name': 'Sam'},
'Mahmoud': {'name': 'Mahmoud'},
'Xiao': {'name': 'Xiao'},
'Olufemi': {'name': 'Olufemi'},
'Kim': {'name': 'Kim'},
'Rafael': {'name': 'Rafael'}
}
So far my solution looks like this:
result_dict = {}
for list_of_dicts in original_dict.values:
for curr_dict in list_of_dicts:
result_dict[curr_dict['name']] = curr_dict
But is there a more pythonic/compact way to do this? Maybe using dict comprehension?
You can use dictionary comprehension.
result = {name['name']: name for k, v in original.items() for name in v}
The inner for loop will iterate through all the key value pairs and the outer will iterate through each name in each value.
Yes, just rewrite your loops as a dict comprehension:
original = {
1: [{'name': 'Sam'}, {'name': 'Mahmoud'}, {'name': 'Xiao'}],
2: [{'name': 'Olufemi'}, {'name': 'Kim'}, {'name': 'Rafael'}]
}
result = {d['name']: d for l in original.values() for d in l}
from pprint import pprint
pprint(result)
Output:
{'Kim': {'name': 'Kim'},
'Mahmoud': {'name': 'Mahmoud'},
'Olufemi': {'name': 'Olufemi'},
'Rafael': {'name': 'Rafael'},
'Sam': {'name': 'Sam'},
'Xiao': {'name': 'Xiao'}}
For some reason my small small brain is having problems with this, I have a list of tuples list = [('name:john','age:25','location:brazil'),('name:terry','age:32','location:acme')]. Im trying to move these values into a dictionary for parsing later. I have made a few attempts, below the latest of these and im not getting all results into the dict, the dict ends up with the last value iterated (its recreating the dict each time).
people = {}
list = [('name:john','age:25','location:brazil'),('name:terry','age:32','location:acme')]
for value in list:
people = {'person': [dict(item.split(":",1) for item in value)]}
You can try this one too:
inlist = [('name:john','age:25','location:brazil'),('name:terry','age:32','location:acme')]
d = []
for tup in inlist:
tempDict = {}
for elem in tup:
elem = elem.split(":")
tempDict.update({elem[0]:elem[1]})
d.append({'person':tempDict})
print(d)
Output:
[{'person': {'location': 'brazil', 'name': 'john', 'age': '25'}}, {'person': {'location': 'acme', 'name': 'terry', 'age': '32'}}]
If you want a dictionary with a key person and values the dictionaries with the people's info, then replace d.append({'person':tempDict}) with d.append(tempDict) and add d = {'person':d} right before printing.
Output:
{'person': [{'location': 'brazil', 'name': 'john', 'age': '25'}, {'location': 'acme', 'name': 'terry', 'age': '32'}]}
You can try this:
l = [('name:john','age:25','location:brazil'),('person:terry','age:32','location:acme')]
people = [{c:d for c, d in [i.split(':') for i in a]} for a in l]
Output:
[{'name': 'john', 'age': '25', 'location': 'brazil'}, {'person': 'terry', 'age': '32', 'location': 'acme'}]
First of all try not to call your list list. This name is protected in python and used usually to get a list out of iterators or ranges etc.
I would make a list of people first and then append each person to the people list as separate dictionary as follows:
people = []
my_list = [('name:john','age:25','location:brazil'),('person:terry','age:32','location:acme')]
for tup in my_list:
person = {}
for item in tup:
splitted = item.split(':')
person.update({splitted[0]:splitted[1]})
people.append(person)
The output then would be this:
[{'age': '25', 'location': 'brazil', 'name': 'john'},
{'age': '32', 'location': 'acme', 'person': 'terry'}]