List to dict in python - python

I have a list with this format
l = ['Rick', 25, 'Student', 'rick#mail.com']
and I need a dict with this format
{'Name': 'Rick', 'Age': 25, 'E-mail': 'rick#mail.com', 'Position': 'Student'}
In my head the solution is iterate over the list and put each value inside the key dict. Are there other (Simplified) solution?

keys = ['name', 'age', 'job', 'email']
values = ['Rick', 25, 'Student', 'rick#mail.com']
key_dict = dict(zip(keys, values))
print(key_dict)
# {'name': 'Rick', 'age': 25, 'job': 'Student', 'email': 'rick#mail.com'}

Use zip() to join the keys and the values in l together, and then convert to a dictionary with dict as seen here:
>>> dict(zip(('Name', 'Age', 'Role', 'E-mail'), l))
{'Name': 'Rick', 'E-mail': 'rick#mail.com', 'Role': 'Student', 'Age': 25}
Or, if you wanted to omit the 'Student' element all together, you could just slice at the third index:
>>> dict(zip(('Name', 'Age', 'E-mail'), l[:2] + l[3:]))
{'Name': 'Rick', 'E-mail': 'rick#mail.com', 'Age': 25}
Or use a generator:
>>> dict(zip(('Name', 'Age', 'E-mail'), (a for a in l if a is not 'Student')))
{'Name': 'Rick', 'E-mail': 'rick#mail.com', 'Age': 25}

You should use zip(). It will merge to lists into an immutable dict.
keys = ['name', 'age', 'position', 'email']
values = ['Rick', 25, 'Student', 'rick#mail.com']
zippeddict = dict(zip(keys, values))

Related

Sort list of dictionaries according to custom ordering

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

Comprehension list of nested dictionary to get values but got keys

Fairly new to list comprehension and have the_list that I want to extract the keys of nested dictionary but I got the values instead. What am I missing or what am I doing wrong?
the_list = [{'size': 0, 'values': [], 'start': 0}, {'size': 2, 'values': [{'user': {'name': 'anna', 'id': 10, 'displayName': 'Anna'}, 'category': 'Secretary'}, {'user': {'name': 'bob', 'id': 11, 'displayName': 'Bobby'}, 'category': 'Manager'}], 'start': 0}, {'size': 1, 'values': [{'user': {'name': 'claire', 'id': 13, 'displayName': 'Clarissa Claire'}, 'category': 'Secretary'}], 'start': 0}]
list_comprehension = []
list_comprehension = [x for x in the_list for x in the_list[1]['values'][0]]
print(list_comprehension)
>> ['user', 'category', 'user', 'category', 'user', 'category']
Want
list_comprehension = [[anna, Secretary], [bob, manager], [claire, Secretary]]
You could use this. I personnally try to avoid nested list comprehension as they are hard to read and debug.
[[x['category'], x['user']['displayName']] for nest_list in the_list for x in nest_list["values"] ]
Output:
[['Secretary', 'Anna'], ['Manager', 'Bobby'], ['Secretary', 'Clarissa Claire']]
EDIT:
A version that doesn't have a nested comprehension list. When doing it I realised that there was one more level than I realised that makes this version a bit long. So in the end I'm not sure which one I would use in prod.
result = []
dict_list = [nest_list["values"] for nest_list in the_list]
for elt in dict_list:
for d in elt:
result.append([d['category'], d['user']['displayName']])
I've come up with this solution, but it is not very readable ...
comprehensionList = [[user['user']['name'], user['category']] for x in the_list for user in x['values']]
# Output
[['anna', 'Secretary'], ['bob', 'Manager'], ['claire', 'Secretary']]

Adding key and value to dictionary in python based on other dictionaries

I am using for loop in python and every loop creates a dictionary. I have the below set of dictionaries created.
{'name': 'xxxx'}
{'name': 'yyyy','age':'28'}
{'name': 'zzzz','age':'27','sex':'F'}
My requirement is to compare all the dictionaries created and find out the missing key values and add the key to missing dictionaries and order every dictionary based on key. Below is the expected output
Expected output:
{'age':'','name': 'xxxx','sex':''}
{'age':'28','name': 'yyyy','sex':''}
{'age':'27','name': 'zzzz','sex':'F'}
How to achieve this in python.
If you want to modify the dicts in-place, dict.setdefault would be easy enough.
my_dicts = [
{'name': 'xxxx'},
{'name': 'yyyy','age':'28'},
{'name': 'zzzz','age':'27','sex':'F'},
]
desired_keys = ['name', 'age', 'sex']
for d in my_dicts:
for key in desired_keys:
d.setdefault(key, "")
print(my_dicts)
prints out
[
{'name': 'xxxx', 'age': '', 'sex': ''},
{'name': 'yyyy', 'age': '28', 'sex': ''},
{'name': 'zzzz', 'age': '27', 'sex': 'F'},
]
If you don't want to hard-code the desired_keys list, you can make it a set and gather it from the dicts before the loop above.
desired_keys = set()
for d in my_dicts:
desired_keys.update(set(d)) # update with keys from `d`
Another option, if you want new dicts instead of modifying them in place, is
desired_keys = ... # whichever method you like
empty_dict = dict.fromkeys(desired_keys, "")
new_dicts = [{**empty_dict, **d} for d in my_dicts]
EDIT based on comments:
This doesn't remove keys that are not there in desired keys.
This will leave only the desired keys:
desired_keys = ... # Must be a set
for d in my_dicts:
for key in desired_keys:
d.setdefault(key, "")
for key in set(d) - desired_keys:
d.pop(key)
However, at that point it might be easier to just create new dicts:
new_dicts = [
{key: d.get(value, "") for key in desired_keys}
for d in my_dicts
]
data = [{'name': 'xxxx'},
{'name': 'yyyy','age':'28'},
{'name': 'zzzz','age':'27','sex':'F'}]
First get the maximum, to get all the keys.
Then use dict.get to get default value as empty string for each of the keys, and sort the dictionary on key, you can combine List-comprehension and dict-comprehension:
allKD = max(data, key=len)
[dict(sorted({k:d.get(k, '') for k in allKD}.items(), key=lambda x:x[0])) for d in data]
OUTPUT:
[{'age': '', 'name': 'xxxx', 'sex': ''},
{'age': '28', 'name': 'yyyy', 'sex': ''},
{'age': '27', 'name': 'zzzz', 'sex': 'F'}]
One approach:
from operator import or_
from functools import reduce
lst = [{'name': 'xxxx'},
{'name': 'yyyy', 'age': '28'},
{'name': 'zzzz', 'age': '27', 'sex': 'F'}]
# find all the keys
keys = reduce(or_, map(dict.keys, lst))
# update each dictionary with the complement of the keys
for d in lst:
d.update(dict.fromkeys(keys - d.keys(), ""))
print(lst)
Output
[{'name': 'xxxx', 'age': '', 'sex': ''}, {'name': 'yyyy', 'age': '28', 'sex': ''}, {'name': 'zzzz', 'age': '27', 'sex': 'F'}]

How can I compare two lists with specific key in dict in python

I want to take two lists with dict value and find the specific values that appear only in first list.
In this case, only compare 'name' key.
a = [
{'name': 'joseph', 'age': 33},
{'name': 'Emma', 'age': 11},
{'name': 'apple', 'age': 44}
]
b = [
{'name': 'apple', 'age': 44},
{'name': 'Emma', 'age': 22}
]
returnOnlyOne(a, b)
would return [{'name': 'joseph', 'age': 33}], for instance.
The set() solution is not for this case.
For efficiency, we first make a set of the names in b, then filter the list a:
from operator import itemgetter
def returnOnlyOne(a, b):
b_names = set(map(itemgetter('name'), b))
only_in_a = list(filter(lambda item: item['name'] not in b_names, a))
return only_in_a
Sample output:
a = [
{'name': 'joseph', 'age': 33},
{'name': 'Emma', 'age': 11},
{'name': 'apple', 'age': 44}
]
b = [
{'name': 'apple', 'age': 44},
{'name': 'Emma', 'age': 22}
]
print(returnOnlyOne(a, b))
# [{'name': 'joseph', 'age': 33}]
If you don't like itemgetter, filter and the like, you can write the same using comprehensions:
def returnOnlyOne(a, b):
b_names = set(item['name'] for item in b)
return [ item for item in a if item['name'] not in b_names]
Use list comprehension with map. (BTW, what's inside your list is called dict):
[d for d in a if d.get('name') not in list(map(lambda x:x.get('name'), b))]
# [{'age': 33, 'name': 'joseph'}]
Explanation:
list(map(lambda x:x.get('name'), b)): gets all name from b
d.get('name') not in: checks if name from a doesn't exist in b. (i.e. appear only in first list)
Nearly the same as the others.
print([ item for item in a if item['name'] not in set(item['name'] for item in b)])

How to compare two lists of dicts for multiple key, value pairs?

I have two lists of dicts, one is a modified subset of the other. I would like to get the elements of list_one that don't appear in list_two, based on two keys. Example:
list_one = [{'name': 'alf', 'age': 25},
{'name': 'alf', 'age': 50},
{'name': 'cid', 'age': 30}]
list_two = [{'name': 'alf', 'age': 25, 'hair_color': 'brown'},
{'name': 'cid', 'age': 30, 'hair_color': 'black'}]
desired_list = [{'name': 'alf', 'age': 50}]
How can I accomplish this? I have a feeling it is with some sort of list comprehension, as such:
desired_list = [x for x in list_one if x['name'] != x2['name'] and x['age'] != x2['age']
for all x2 in list_two]
I think this is easily done with two comprehensions as:
Code:
have_2 = {(d['name'], d['age']) for d in list_two}
extra = [d for d in list_one if (d['name'], d['age']) not in have_2]
This first creates a set of tuples which we already have, then checks which dicts do not match any of these existing keys.
Test Code:
list_one = [{'name': 'alf', 'age': 25},
{'name': 'alf', 'age': 50},
{'name': 'cid', 'age': 30}]
list_two = [{'name': 'alf', 'age': 25, 'hair_color': 'brown'},
{'name': 'cid', 'age': 30, 'hair_color': 'black'}]
have_2 = {(d['name'], d['age']) for d in list_two}
extra = [d for d in list_one if (d['name'], d['age']) not in have_2]
print(extra)
Results:
[{'name': 'alf', 'age': 50}]
Yet another possible solution:
>>> list(filter(lambda x: not any([set(x.items()).issubset(y.items()) for y in list_two]), list_one))
[{'age': 50, 'name': 'alf'}]
or:
>>> s2 = [set(i.items()) for i in list_two]
>>> list(filter(lambda x: not any([set(x.items()).issubset(y) for y in s2]), list_one))
[{'age': 50, 'name': 'alf'}]
The advantage of this approach is that it does not need to know the "keys" ('age' and 'name') present in both dictionary sets.
Use this:-
new_list = [i for i,j in zip(list_one,list_two) if i['name']!=j['name'] and i['age']!=j['age']]
print (new_list)
Output
[{'name': 'alf', 'age': 50}]
An efficient way would be to convert your two structures to dicts, keyed by the two values, then create the result dict:
key = lambda dct: (dct['name'], dct['age'])
d1 = { key(dct): dct for dct in list_one }
d2 = { key(dct): dct for dct in list_two }
desired_d = { k:v for k,v in d1.items() if k not in d2 }
print(desired_d)
print(desived_d.values())
diff = [
e for e in list_one
if (e['name'], e['age']) not in set((e['name'], e['age']) for e in list_two)
]
print diff

Categories

Resources