How to selectively create a dictionary from an existing one? - python

I have two dictionaries like below which have common keys:
dictionary1 = {1: 'a', 2: 'b' , 3: 'c'}
dictionary2 = {1: 'no', 2: 'yes' ,3:'yes'}
I want to create a new dictionary with the key and values of dictionary1 only if the corresponding values of the dictionary2 key has "yes".
Expected output:
{2: 'b', 3: 'c'}
What I have tried:
dictionary1 = {1: 'a', 2: 'b' , 3: 'c'}
dictionary2 = {1: 'no', 2: 'yes' ,3:'yes'}
common_pairs = dict()
for key,value in dictionary2.items():
for key,v in dictionary1.items():
if(value == "yes"):
common_pairs[key] = v

You don't need a nested for loop. Just a single iteration over dictionary1 items with corresponding O(1) lookup in dictionary2:
With a dict comprehension this would look like:
>>> dictionary1 = {1: 'a', 2: 'b' , 3: 'c'}
>>> dictionary2 = {1: 'no', 2: 'yes' ,3:'yes'}
>>> new = {k: v for k, v in dictionary1.items() if dictionary2[k] == 'yes'}
>>> new
{2: 'b', 3: 'c'}
With a traditional for loop:
>>> new = {}
>>> for k, v in dictionary1.items():
... if dictionary2[k] == 'yes':
... new[k] = v
...
>>> new
{2: 'b', 3: 'c'}

You could do this in a dictionary comprehension:
common_pairs = { key:value for key,value in dictionary1.items()
if dictionary2.get(key,"") == "Yes" }
The get function provides a default value if the key is not present. this will prevent errors if a key in dictionary1 is absent from dictionary2.

You can just iterate through dict2, check if the element is in dict1 and that the key is yes, and then add it to the dictionary.
dictionary1 = {1: 'a', 2: 'b' , 3: 'c'}
dictionary2 = {1: 'no', 2: 'yes' ,3:'yes'}
common_pairs = dict()
for key in dictionary2:
if key in dictionary1 and dictionary2[key] == 'yes':
common_pairs[key] = dictionary1[key]

Related

How to merge two python dictionaries with common keys and values both [duplicate]

This question already has answers here:
How to merge dicts, collecting values from matching keys?
(17 answers)
Closed 2 months ago.
I have two dictionaries
a = {1:'John',2:'hello',3:'python',5:'ABC'}
b = {1:'Doe',2:'world',3:'python',4:'XYZ'}
How can i merge them in a way to have:
new_dic = {1:['John','Doe'],2:['hello','world'],3:'python',4:'XYZ',5:'ABC'}
Here 'python' is a common entry, while 'XYZ', and 'ABC' are only present in respective dictionary.
One approach:
a = {1: 'John', 2: 'hello', 3: 'python', 5: 'ABC'}
b = {1: 'Doe', 2: 'world', 3: 'python', 4: 'XYZ'}
res = a.copy()
for k, v in b.items():
if k in res and v != res[k]:
res[k] = [res[k], v]
else:
res[k] = v
print(res)
Output
{1: ['Doe', 'John'], 2: ['hello', 'world'], 3: 'python', 5: 'ABC', 4: 'XYZ'}
dict1 = {1:'John',2:'hello',3:'python',5:'ABC'}
dict2 = {1:'Doe',2:'world',3:'python',4:'XYZ'}
dict3 = {}
for key in dict1.keys():
if key in dict2.keys():
dict3[key] = [dict1[key], dict2[key]]
else:
dict3[key] = dict1[key]
for key in dict2.keys():
if key not in dict3.keys():
dict3[key] = dict2[key]
print(dict3)
Simply check for similar keys and then update:
a = {1:'John',2:'hello',3:'python',5:'ABC'}
b = {1:'Doe',2:'world',3:'python',4:'XYZ'}
res = {}
for k, v in a.items():
if k in b.keys() and v != b[k]: # check if key is there in other dict
res[k] = [a[k],b[k]]
del b[k] # clear b for further efficiency
else:
res[k] = a[k]
for key in b.keys():
res[key] = b[key]
print(res)
Output:
{1: ['John', 'Doe'], 2: ['hello', 'world'], 3: 'python', 5: 'ABC', 4: 'XYZ'}
Edit: Thanks to #Yash Mehta

How to merge keys of dictionary which have the same value?

I need to combine two dictionaries by their value, resulting in a new key which is the list of keys with the shared value. All I can find online is how to add two values with the same key or how to simply combine two dictionaries, so perhaps I am just searching in the wrong places.
To give an idea:
dic1 = {'A': 'B', 'C': 'D'}
dic2 = {'D': 'B', 'E': 'F'}
Should result in:
dic3 = {['A', 'D']: 'B', 'C': 'D', 'E': 'F'}
I am not sure why you would need such a data structure, you can probably find a better solution to your problem. However, just for the sake of answering your question, here is a possible solution:
dic1 = {'A':'B', 'C':'D'}
dic2 = {'D':'B', 'E':'F'}
key_list = list(dic2.keys())
val_list = list(dic2.values())
r = {}
for k,v in dic1.items():
if v in val_list:
i = val_list.index(v) #get index at value
k2 = key_list[i] #use index to retrive the key at value
r[(k, k2)] = v #make the dict entry
else:
r[k] = v
val_list = list(r.values()) #get all the values already processed
for k,v in dic2.items():
if v not in val_list: #if missing value
r[k] = v #add new entry
print(r)
output:
{('A', 'D'): 'B', 'C': 'D', 'E': 'F'}
You can't assign a list as a key in a python dictionary since the key must be hashable and a list is not an ashable object, so I have used a tuple instead.
I would use a defaultdict of lists and build a reversed dict and in the end reverse it while converting the lists to tuples (because lists are not hashable and can't be used as dict keys):
from collections import defaultdict
dic1 = {'A':'B', 'C':'D'}
dic2 = {'D':'B', 'E':'F'}
temp = defaultdict(list)
for d in (dic1, dic2):
for key, value in d.items():
temp[value].append(key)
print(temp)
res = {}
for key, value in temp.items():
if len(value) == 1:
res[value[0]] = key
else:
res[tuple(value)] = key
print(res)
The printout from this (showing the middle step of temp) is:
defaultdict(<class 'list'>, {'B': ['A', 'D'], 'D': ['C'], 'F': ['E']})
{('A', 'D'): 'B', 'C': 'D', 'E': 'F'}
If you are willing to compromise from 1-element tuples as keys, the second part will become much simpler:
res = {tuple(value): key for key, value in temp.items()}

add a second value to a key (dict) python

I need to make sure I don't have more than one of the same keys, if so, leave the first one and add their value (make it a list) to the existing key
this is what I tried:
my_dict = {1: "A", 2: "B", 1: "C"}
new_dict={}
list_keys = list(my_dict.keys())
list_values = list(my_dict.values())
for i in range(len(list_values)):
if list_keys[i] in new_dict.keys():
new_dict[list_keys[i]].append(list(list_values[i]))
else:
new_dict.update({list_keys[i]: list_values[i]})
return new_dict
The result required:
{1: ["A", "C"], 2: ["B"]}
The most concise way of reversing a dict like that uses a defaultdict:
from collections import defaultdict
d = {"A": 1, "B": 2, "C": 1}
rev = defaultdict(list)
for k, v in d.items():
rev[v].append(k)
rev
# defaultdict(<class 'list'>, {1: ['A', 'C'], 2: ['B']})
That first line doesn't make sense. A dictionary cannot have two values for the same key, so when you run that first line, the resulting dictionary is:
my_dict = {1: 'A', 2: 'B', 1: 'C'}
print(my_dict)
# {1: 'C', 2: 'B'}
What you could do is iterate over lists of desired keys and values, and build the dictionary that you want that way:
my_keys = [1, 2, 1]
my_vals = ['A', 'B', 'C']
my_dict = {}
for k, v in zip(my_keys, my_vals):
if k in my_dict.keys():
if not isinstance(my_dict[k], list):
my_dict[k] = [my_dict[k]] # convert to a list
my_dict[k].append(v)
else:
my_dict[k] = v
print(my_dict)
# {1: ['A', 'C'], 2: 'B'}
Based on the comments, you originally had a dictionary in_dict = {'A': 1, 'B': 2, 'C':1}. Given this in_dict, you can get the desired result by setting my_keys = in_dict.values() and my_vals = in_dict.keys() in the code above.
Using comprehensions if you want
a = {"A":1, "B":2, "C":1}
{value: [item_[0] for item_ in a.items() if item_[1] == value] for value in set(a.values())}
Output
{1: ['A', 'C'], 2: ['B']}

switch key and values in a dict of lists

Hello Stackoverflow people,
I have a nested dictionary with lists as values and I want to create a dict where all the list entries get their corresponding key as value.
Example time!
# what I have
dict1 = {"A":[1,2,3], "B":[4,5,6], "C":[7,8,9]}
# what I want
dict2 = {1:"A", 2:"A", 3:"A", 4:"B", 5:"B", 6:"B", 7:"C", 8:"C", 9:"C"}
Any help will be much appreciated!
Try this
dict1 = {"A":[1,2,3], "B":[4,5,6], "C":[7,8,9]}
dict2= {}
for keys,values in dict1.items():
for i in values:
dict2[i]=keys
print(dict2)
Output
{1: 'A', 2: 'A', 3: 'A', 4: 'B', 5: 'B', 6: 'B', 7: 'C', 8: 'C', 9: 'C'}
Hope it helps
Use dictionary comprehension:
d = {'a': 'b', 'c': 'd', 'e': 'f'}
d2 = dict((v1, k) for k, v in d.items() for v1 in v) # Here is the one-liner
assuming your key: value dictionary contains list as a value and using dict comprehension.
Using a second loop to iterate over the list present in original dictionary.
{item: key for key, value in dict1.items() for item in value}

Group dictionaries based on values that differ

Grouping dictionaries based on similar values is easy, but I have trouble thinking of a good way of doing the opposite: grouping dictionaries where one of the key's value differ from the rest.
For instance, take these:
a = {1: 'a', 2: 'b', 3:'c'}
b = {1: 'a', 2: 'b', 3:'d'}
c = {1: 'c', 2: 'b', 3:'d'}
These can be grouped into two different sets, where one of the key values differ:
# Expected output:
{3: {a, b}, # Differs on 3
1: {b, c}} # Differs on 1
I have trouble thinking of a good way of implementing such a function. Do you have any suggestions about how to go forward?
You can get a dictionary difference, assuming that the keys and values are hashable, by usings sets on the items. You can then get a list of pairs of dicts, and what their difference is:
a = {1: 'a', 2: 'b', 3:'c'}
b = {1: 'a', 2: 'b', 3:'d'}
c = {1: 'c', 2: 'b', 3:'d'}
def diff_dict(dicta, dictb):
aset = set(dicta.items())
bset = set(dictb.items())
diff = aset ^ bset
return tuple(set(x[0] for x in diff))
print diff_dict(a, b)
(3,)
all_dicts = [a,b,c]
listgroup = []
for dicta, dictb in itertools.combinations(all_dicts, 2):
key = diff_dict(dicta, dictb)
listgroup.append((key, (dicta, dictb)))
If you only want single items, gate the append with an if len(key) == 1.

Categories

Resources