Merge values in a list of dictionaries on key - python

i have that array of dicts:
[{'dog': 'dog-1'}, {'monkey': 'monkey-1'}, {'buffalo': 'buffalo-6'}, {'dog': 'dog-2'},{'pig': 'pig-3'}, {'monkey': 'monkey-6'}, {'monkey': 'monkey-6'}]
And I need to put everyone that has the same key in the same dict. I need that result:
[{'dog': ['dog-1', 'dog-2']}, {'monkey': ['monkey-1', 'monkey-6', 'monkey-6']}, {'buffalo': ['buffalo-6']}, {'pig': ['pig-3']}]

Use a defaultdict:
from collections import defaultdict
lst = [{'dog': 'dog-1'}, {'monkey': 'monkey-1'}, {'buffalo': 'buffalo-6'}, {'dog': 'dog-2'},{'pig': 'pig-3'}, {'monkey': 'monkey-6'}, {'monkey': 'monkey-6'}]
output = defaultdict(list)
for d in lst:
for k,v in d.items():
output[k].append(v)

The general idea is, while you're iterating over the list, you want to know if you've reached a dictionary whose key you've already seen before. If you've already seen that key, then you want to append its value to the value of the matching key; if not, you want to create a new key with a default value (in this case an empty list). You can use dict.setdefault to do that.
out = {}
for d in lst:
for k, v in d.items():
out.setdefault(k, {}).setdefault(k, []).append(v)
out = list(out.values())
Output:
[{'dog': ['dog-1', 'dog-2']},
{'monkey': ['monkey-1', 'monkey-6', 'monkey-6']},
{'buffalo': ['buffalo-6']},
{'pig': ['pig-3']}]

Related

inversing a dictionary in python with duplicate values

I need to inverse a dictionary so that each old value will now be a key and the old keys will be the new values.
The trick is that there could be multiple values that are the same in the old dictionary so I need each value in the new dictionary to be a list, and if there were identical values in the old dictionary then they both will be in the list of the value of the new dictionary.
for example:
the dictionary {"python" : 1, "is" : 1, "cool" : 2}
would end up as: {1 : ["python", "is"], 2 : ["cool"]}
this is what I tried:
def inverse_dict(my_dict):
new_dict = {}
values_list = list(my_dict.values())
new_dict = new_dict.fromkeys(values_list)
for key in new_dict:
new_dict[key] = []
for old_key in my_dict:
new_dict[my_dict[old_key]] = list(new_dict[my_dict[old_key]]).append(old_key)
return new_dict
Would greatly appreciate any help with my approach (and better approaches to the problem) as I am very new to Python, thanks!
You can use dict.setdefault check if a key exists in the dictionary and if not, create new value (in this case empty list []):
d = {"python" : 1, "is" : 1, "cool" : 2}
reversed_d = {}
for k, v in d.items():
reversed_d.setdefault(v, []).append(k)
print(reversed_d)
Prints:
{1: ['python', 'is'], 2: ['cool']}
This can be more explicitly rewritten as:
d = {"python" : 1, "is" : 1, "cool" : 2}
reversed_d = {}
for k, v in d.items():
if v not in reversed_d:
reversed_d[v] = [k]
else:
reversed_d[v].append(k)
print(reversed_d)
You can use a defaultdict to avoid the pre-fill step
from collections import defaultdict
def inverse_dict(my_dict: dict):
new_dict = defaultdict(list)
for k, v in my_dict.items():
new_dict[v].append(k)
return new_dict
Though I prefer #azro's answer with the default dict, another solution is doing it with dictionary and list comprehensions.
It looks like this:
{value : [key for key in my_dict if my_dict[key] == value] for value in set(my_dict.values())}
What it does is runs over the values of the dictionary without duplicates - set(my_dict.values()).
It builds every value as a key (because it's on the left side of the ":").
And its value is a list of the keys that point to that value - [key for key in my_dict if my_dict[key] == value].

Getting a specific value of a key in a dictionary?

I have a dictionary like this:
d = {'k1':[0.2,0.65,0.23], 'k2':[0.32,1.2,3.3], 'k3':[1.8,0.6,0.4], ...}
So, I want to get a list of the key and the second value of each key in a list. I have tried this code:
names = list(d.keys())
values = list(d.values())
The first line is correct and gives me the list of all keys, but the second line provides all the values, which is not what I needed. So I need only the second or the third value of each key. Any suggestions?
Iterate over the dict and get the v[1] for each key, in a new dict:
d = {'k1':[0.2,0.65,0.23], 'k2':[0.32,1.2,3.3], 'k3':[1.8,0.6,0.4]}
print({k:v[1] for k,v in d.items()})
OUTPUT:
{'k1': 0.65, 'k2': 1.2, 'k3': 0.6}
try:
mylist = [(k, v[1]) for k, v in d.items()]
{k:v[1] for k,v in d.items()}
Create a new dict with the second value from the list-value of the original dict using a dictionary comprehension.
This will help you:
names = list(d.keys())
values = [v[1] for v in d.values()]
This iterate key and values per key
for k,v in d.items():
print("Key: %s" %k)
print("Values: %s" %v)
print("-"*8)
>>> import numpy as np
>>> d = {'k1':[0.2,0.65,0.23], 'k2':[0.32,1.2,3.3], 'k3':[1.8,0.6,0.4]}
>>> np.array(list(d.values()))[:,1]
Output:
array([0.65, 1.2 , 0.6 ])
d = {k1:[0.2,0.65,0.23], k2:[0.32,1.2,3.3], k3:[1.8,0.6,0.4], ...}
for fetching only 2nd element from the values, Below code will print only 2nd elements of each key
example - [v[1] for k,v in d.iteritems()]
prints [0.65,1.2,0.6]
for fetching key:value
{k:v[1] for k,v in d.iteritems()}
prints {'k1':0.65,'k2':1.2,'k3':0.6}
for fetching 2nd and 3rd element both , something like this can be done
{k:[v[1],v[2]] for k,v in d.iteritems()}

How do I create a dictionary from two lists in python while maintaining all key value information?

Example:
last_names = ['Bakir','Jose','Jose','Pierce']
university = ['Davis', 'Stanford', 'George Town', 'Berkeley']
Desire the Following
resulting_dictionary = {'Bakir':'Davis', 'Jose': ['Stanford', 'George Town'], 'Pierce':'Berkeley'}
I've tried the following
dictionary = {key:value for key, value in zip(last_names, university)}
But obtained the following:
{'Bakir': 'Davis', 'Jose': 'George Town', 'Pierce': 'Berkeley'}
Due to duplicate key value in last name list.
Thoughts?
Use defaultdict
from collections import defaultdict
d = defaultdict(list)
for k, v in zip(last_names, university):
d[k].append(v)
You can use the dict.setdefault method to initialize new keys with sub-lists:
dictionary = {}
for k, v in zip(last_names, university):
dictionary.setdefault(k, []).append(v)
You need to set the value to a list, and check whether the key already exists and append to it.
dictionary = {}
for key, value in zip(last_names, university):
if key in dictionary:
dictionary[key].append(value)
else:
dictionary[key] = [value]
This will make all the values lists. It's generally easier if you're consistent about your data format, not mixing strings and lists. So the result will be:
{'Bakir':['Davis'], 'Jose': ['Stanford', 'George Town']], 'Pierce':['Berkeley']}
Assuming, as the question seems to imply, that a list is not desired if only one value is present for a key, a simple flattening post-step can be used to achieve the specified result.
from collections import defaultdict
d = defaultdict(list)
for k, v in zip(last_names, university):
d[k].append(v)
# flatten single entry lists back to a string
d = { k: v[0] if len(v) == 1 else v for k, v in d.items() }
Try this:
my_dict = {}
for key, value in zip(last_names, university):
if key in my_dict:
old_value = my_dict[key]
if isinstance (old_value, str):
my_dict[key] = [old_value, value]
else:
old_value.add (value)
else:
my_dict[key] = value

Python: How to combine two dictionaries in python such that the resultant contains key as the value from the first

I have two dictionaries as follows:
mydictionary_1 = {1:'apple',2:'banana'}
mydictionary_2 = {1:50,2:30}
The resultant dictionary should be such that it takes the key as the value of first dictionary.
Result_dictionary= {'apple':50, 'banana':30}
You can use a dictionary comprehension using the values of the first dictionary as the keys of the resulting dictionary. This assumes all keys of the first are present in the second dict
{v: dict2[k] for k, v in dict1.items()}
you can also add a check for the presence of the keys in the second dictionary
{v: dictionary_2[k] for k, v in dictionary_1.items() if k in dictionary_2}
Loop through one of the dictionaries and check if the value for a key in mydictionary_1 exists in mydictionary_2.
You can achieve this using python's dictionary comprehension -
Result_dictionary = { v:mydictionary_2[k] for k,v in mydictionary_1.iteritems() if k in mydictionary_2.keys()}
To see how this list comprehension is working you can even use general for loop to loop through each key, value pair in mydictionary_1
for key,value in mydictionary_1.iteritems():
if key in mydictionary_2.keys():
Result_dictionary[value]=mydictionary_2[key]
Dictionary comprehension is an ideal solution for this one, as previously mentioned. Here is a for loop example:
def combine_dictionaries(dict1, dict2):
result_dictionary = {}
for key in dict1.keys():
result_dictionary[dict1[key]] = dict2[key]
return result_dictionary
combine_dictionaries({1:'apple', 2:'banana'}, {1:50, 2:30})
>>>{'apple': 50, 'banana': 30}
This assumes all values of the dict1 are present in the dict2.
def dict_cross_match(dict1, dict2):
new_dict = {}
for item in dict1.keys():
if item in dict2.keys():
new_dict[dict1[item]] = dict2[item]
return new_dict
mydictionary_1 = {1:'apple',2:'banana'}
mydictionary_2 = {1:50,2:30}
print(dict_cross_match(mydictionary_1, mydictionary_2))

How to split list inside a dictionnary to create a new one?

I've been struggling on something for the day,
I have a dictionnary under the format
dict = {a:[element1, element2, element3], b:[element4, element5, element6]...}
I want a new dictionnary under the form
newdict = {a:element1, b:element4...}
Meaning only keeping the first element of the lists contained for each value.
You can use a dictionary comprehension:
{k: v[0] for k, v in d.items()}
# {'a': 'element1', 'b': 'element4'}
Hopefully this helps.
I like to check if the dictionary has a key before overwriting a keys value.
dict = {a:[element1, element2, element3], b:[element4, element5, element6]}
Python 2
newDict = {}
for k, v in dict.iteritems():
if k not in newDict:
# add the first list value to the newDict's key
newDick[k] = v[0]
Python 3
newDict = {}
for k, v in dict.items():
if k not in newDict:
# add the first list value to the newDict's key
newDick[k] = v[0]

Categories