Python - Create list of dictionaries from multiple lists of values - python

I have multiple lists of data, for example: age, name, gender, etc. All of them in order, meaning that the x record of every list belongs to the same person.
What I'm trying to create is a list of dictionaries from these lists in the best pythonic way. I was able to create it using one of the lists, but not sure how to scale it from there.
What I currently have:
ages = [20, 21, 30]
names = ["Jhon", "Daniel", "Rob"]
list_of_dicts = [{"age": value} for value in ages]
It returns:
[{'age': 20}, {'age': 21}, {'age': 30}]
What I want:
[{'age': 20, 'name': 'Jhon'}, {'age': 21, 'name': 'Daniel'}, {'age': 30, 'name': 'Rob'}]

You need to zip:
ages = [20, 21, 30]
names = ["Jhon", "Daniel", "Rob"]
list_of_dicts = [{"age": value, 'name': name}
for value, name in zip(ages, names)]
You can take this one step further and use a double zip (useful if you have many more keys):
keys = ['ages', 'names']
lists = [ages, names]
list_of_dicts = [dict(zip(keys, x)) for x in zip(*lists)]
output:
[{'age': 20, 'name': 'Jhon'},
{'age': 21, 'name': 'Daniel'},
{'age': 30, 'name': 'Rob'}]

Less obvious code than #mozway's, but has imho one advantage - it relies only on a single definition of a mapping dictionary so if you need to add/remove keys you have to change only one k:v pair.
ages = [20, 21, 30]
names = ["Jhon", "Daniel", "Rob"]
d = {
"name" : names,
"age" : ages
}
list_of_dicts = [dict(zip(d,t)) for t in zip(*d.values())]
print(list_of_dicts)

Related

How to ignore a single/multiple keys of all the dictionaries while looping over a list of dictionaries?

I am looping over a list of dictionaries and I have to drop/ignore either one or more keys of the each dictionary in the list and write it to a MongoDB. What is the efficient pythonic way of doing this ?
Example:
employees = [
{'name': "Tom", 'age': 10, 'salary': 10000, 'floor': 10},
{'name': "Mark", 'age': 5, 'salary': 12000, 'floor': 11},
{'name': "Pam", 'age': 7, 'salary': 9500, 'floor': 9}
]
Let's say I want to drop key = 'floor' or keys = ['floor', 'salary'].
Currently I am using del employees['floor'] inside the loop to delete the key and my_collection.insert_one() to simply write the dictionary into my MongoDB.
My code:
for d in employees:
del d['floor']
my_collection.insert_one(d)
The solution you proposed is the most efficient to use since you have no control on what happens inside the method insert_one.
If you have more keys, just loop over them:
ignored_keys = ['floor', 'salary']
for d in employees:
for k in ignored_keys:
del d[k]
my_collection.insert_one(d)
Let's say you want to drop keys = ['floor', 'salary']. You can try:
exclude_keys = ['salary', 'floor']
for d in employees:
my_collection.insert_one({k: d[k] for k in set(list(d.keys())) - set(exclude_keys)})

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)}

Python creating dictionary from list and tuple

When I iterate over a dictionary like so:
dict2={
'Joe':('Caucasian','Male', 35, 7.5),
'Kevin':('Black','Male', 55, 9.5),
More tuples here like the one above
}
The data is bigger but it doesn't matter here.
What I am trying to accomplish is to create a new dictionary with the information from the tuples. Like so:
dict_i_want = {
"Name": Joe,
"Ethiniticy": "Caucasian",
"Gender":"Male",
"Voter_age": 35,
"Score": 7.5
}
Here is my code:
dict_i_want = {}
for k,v in dict2.items():
dict_i_want["Name"] = k
dict_i_want['Ethiniticy'] = v[0]
dict_i_want['Gender'] = v[1]
dict_i_want['Voter_age'] = v[2]
dict_i_want['Score'] = v[3]
But when I do
print(dict_i_want)
{'Name': 'Kevin', 'Ethiniticy': 'Black', 'Gender': 'Male', 'Voter_age': 55, 'Score': 9.5}
The result is just the last tuple that I have in mydict2. No all the tuples.
What I am doing wrong if I have the loop?
PS: I don't want to use any modules or import anything here. No built-in function like zip() or something like that. I want to hard code the solution
#ForceBru answered your question - your best bet is a list of dictionaries unless you want to create a dictionary of dictionaries with unique keys for each sub-dictionary. Going with the list approach you could do something like this:
Example:
from pprint import pprint
dict2 = {
'Joe': ('Caucasian', 'Male', 35, 7.5),
'Kevin': ('Black', 'Male', 55, 9.5),
}
dicts_i_want = [
{"name": name, "ethnicity": ethnicity, "gender": gender, "voter_age": voter_age, "score": score}
for name, (ethnicity, gender, voter_age, score) in dict2.items()
]
pprint(dicts_i_want)
Output:
[{'ethnicity': 'Caucasian',
'gender': 'Male',
'name': 'Joe',
'score': 7.5,
'voter_age': 35},
{'ethnicity': 'Black',
'gender': 'Male',
'name': 'Kevin',
'score': 9.5,
'voter_age': 55}]
Dict keys has to be unique. You're just overwriting your dict each cycle in your loop. It's just how dicts work.

Move data from key to value in Python dictionary

I have a python dict:
{'John': 23, 'Matthew': 8, 'Peter': 45}
I want to create a D3 pie chart and need to move my data from the keys so that I can access the values. So I want to end up with:
[
{name: 'John', age: 23},
{name: 'Matthew', age: 8},
{name: 'Peter', age: 45}
]
How can I do this dynamically (given that I may not know what the current key is, eg. 'John')?
data = [{"name": key, "age": value} for key, value in my_dict.items()]
An example:
>>> my_dict = {'John': 23, 'Matthew': 8, 'Peter': 45}
>>> data = [{"name": key, "age": value} for key, value in my_dict.items()]
>>> data
[{'age': 8, 'name': 'Matthew'}, {'age': 23, 'name': 'John'}, {'age': 45, 'name': 'Peter'}]
If you are trying to create a javascript friendly representation of the data, then you will need to convert the list of dictionaries to json.

Python: How to sort a list of dictionaries by several values?

I want to sort a list at first by a value and then by a second value. Is there an easy way to do this? Here is a small example:
A = [{'name':'john','age':45},
{'name':'andi','age':23},
{'name':'john','age':22},
{'name':'paul','age':35},
{'name':'john','age':21}]
This command is for sorting this list by 'name':
sorted(A, key = lambda user: user['name'])
But how I can sort this list by a second value? Like 'age' in this example.
I want a sorting like this (first sort by 'name' and then sort by 'age'):
andi - 23
john - 21
john - 22
john - 45
paul - 35
Thanks!
>>> A = [{'name':'john','age':45},
{'name':'andi','age':23},
{'name':'john','age':22},
{'name':'paul','age':35},
{'name':'john','age':21}]
>>> sorted(A, key = lambda user: (user['name'], user['age']))
[{'age': 23, 'name': 'andi'}, {'age': 21, 'name': 'john'}, {'age': 22, 'name': 'john'}, {'age': 45, 'name': 'john'}, {'age': 35, 'name': 'paul'}]
This sorts by a tuple of the two attributes, the following is equivalent and much faster/cleaner:
>>> from operator import itemgetter
>>> sorted(A, key=itemgetter('name', 'age'))
[{'age': 23, 'name': 'andi'}, {'age': 21, 'name': 'john'}, {'age': 22, 'name': 'john'}, {'age': 45, 'name': 'john'}, {'age': 35, 'name': 'paul'}]
From the comments: #Bakuriu
I bet there is not a big difference between the two, but itemgetter avoids a bit of overhead because it extracts the keys and make the tuple during a single opcode(CALL_FUNCTION), while calling the lambda will have to call the function, load the various constants(which are other bytecodes) finally call the subscript (BINARY_SUBSCR), build the tuple and return it... that's a lot more work for the interpreter.
To summarize: itemgetter keeps the execution fully on the C level, so it's as fast as possible.
from operator import itemgetter
sorted(your_list, key=itemgetter('name', 'age'))
Here is the alternative general solution - it sorts elements of dict by keys and values.
The advantage of it - no need to specify keys, and it would still work if some keys are missing in some of dictionaries.
def sort_key_func(item):
""" helper function used to sort list of dicts
:param item: dict
:return: sorted list of tuples (k, v)
"""
pairs = []
for k, v in item.items():
pairs.append((k, v))
return sorted(pairs)

Categories