Merge 2 dictionaries in Python - python

I have 2 dictionaries.
dict1={('SAN RAMON', 'CA'): 1, ('UPLAND', 'CA'): 4, ('POUGHKEESIE', 'NY'): 3, ('CATTANOOGA', 'TN'): 1}
dict2={('UPLAND', 'CA'): 5223, ('PORT WASHING', 'WI'): 11174, ('PORT CLINTON', 'OH'): 6135, ('GRAIN VALLEY', 'MO'): 10352, ('GRAND JUNCTI', 'CO'): 49688, ('FAIRFIELD', 'IL'): 5165}
These are just samples, in reality each dict has hundreds of entries. I am trying to merge the two dictionaries and create dict 3 that contains {dict1.values(): dict2.values()} but only if that city appears in both dicts. So, one entry in dict3 would look like
{4:5223} # for 'UPLAND', 'CA' since it appears in both dict1 and dict2
This is just a small step in a larger function I am writing. I was going to try something like :
for item in dict1.keys():
if item not in dict2.keys():
del item
return dict[(dict1.keys())=(dict2.keys())]
I can't figure out how to make sure the number of complaints from dict1 matches the same city it is being referred to in dict2.

Here's what I think you want (demo):
dict3 = dict((dict1[key], dict2[key]) for key in dict1 if key in dict2)
Expanded a little, it looks like this:
dict3 = {}
for key in dict1:
if key in dict2:
dict3[dict1[key]] = dict2[key]

The common keys are:
set(dict1.keys()) & set(dict2.keys())
create dict 3 that contains {dict1.values(): dict2.values()}
This doesn't make sense, dictionaries are key-value pairs... what do you really want? Tip:
dict3 = {}
for k in set(dict1.keys()) & set(dict2.keys()):
dict3[dict1[k]]=dict2[k]
{4: 5223}

The straightforward way would be to check each key in one for membership in the other:
result = {}
for key in dict1:
if key in dict2:
result[dict1[key]] = dict2[key]
You could also try converting them into a set or frozenset and taking their intersection, but it's not clear to me whether that will be faster or not:
keys_in_both = frozenset(dict1) & frozenset(dict2)
result = dict((dict1[key], dict2[key]) for key in keys_in_both)

Related

Matching the values of one dictionary to the keys of another dictionary (Python)

Evening All,
Hope you are well.
My Objective
I am trying to match the values of one dictionary to the keys of another.
dict1 has keys but no values
dict2 has keys and values
dict2 has values that can be found as keys in dict1. I'm attempting to write code that identifies which values in dict2 match the keys in dict1.
My Attempt
Commented code is below.
dict1 = {('dict1_key1',): [], ('dict1_key2',): []} #dictionary with keys, but no values;
for i in dict2.keys(): #iterate through the keys of dict2
for x in dict2[i]: #reaching every element in tuples in dict2
if x == dict1.keys(): #if match found in the name of keys in dict1
print(f"{i} holding {x}.") #print which key and value pair in dict 2 match the keys in dict1
The code works if I write the for loop as follows:
for i in dict2.keys(): #iterate through the keys of dict2
for x in dict2[i]: #reaching every element in tuples in dict2
if x == dict1_key1 or x == dict1_key2(): #if match found in the name of keys in dict1
print(f"{i} holding {x}.") #print which key and value pair in dict 2 match the keys in dict1
However, dict1 in reality needs to be able to contain an varying number of keys which is why I had hoped that if x == dict1.keys(): would work.
Any feedback would be greatly appreciated.
#Mark Meyer
Examples values as requested:
dict1 = {('Tower_001',): [], ('Tower_002'): []}
dict2 = {1: 'Block_A', 'Tower_001'] #first key in dict2
#skipping keys 2 through 13
{14: ['Block_N', 'Tower_002']#last key in dict2
You can make sets of all the value in the dict1.keys and dict2.value. Then just take the intersection of those sets to find keys that are also values:
dict1 = {('Tower_001',): [], ('Tower_005',): [], ('Tower_002',): []}
dict2 = {1: ['Block_A', 'Tower_001'], #first key in dict2
14: ['Block_N', 'Tower_002']} #last key in dict2
set(k for l in dict2.values() for k in l) & set(k for l in dict1.keys() for k in l)
# {'Tower_001', 'Tower_002'}

iterate 2 dicts and compare values then append inner list

I am faced with a situation where I need to iterate nested dicts with same outermost keys, compare inner key value to inner key value of other dict then append. Below will help to understand:
{AD:{(62,'VMX','Barcelona','ES'): ['123','567','666'}} #dict1 many more rows
{AD:{(151,'CMXS','','ES','62'): ['345','6754']}} #dict 2 many more rows
So I need to iterate both dicts, compare tuple key[0] of dict1 == tuple key[4] of dict2, if they match append inner list in dict1 with inner list in dict2.
after this dict1 looks like
{AD:{(62,'VMX','Barcelona','ES'): ['123','567','666','345','6754'}}
Wrote this code but it not working as expected
for k,v in dict1.items():
if len(v)!= 0:
for c,a in dict2.items():
if len(a)!= 0:
for k2,v2 in v.items():
for c2,a2 in a.items():
if str(k2[0]) == c2[4]:
v2.append(a2)
dict1 = {"AD":{(62,'VMX','Barcelona','ES'): ['123','567','666']}} #dict1 many more rows
dict2 = {"AD":{(151,'CMXS','','ES','62'): ['345','6754']}} #dict 2 many more rows
# create a simplified map of dict2
dict3 = {}
for outer_key, outer_value_dict in dict2.items():
for inner_key_tuple, inner_value_list in outer_value_dict.items():
new_key = (outer_key, inner_key_tuple[4]) # e.g. (AD, 62)
dict3.setdefault(new_key, []).extend(inner_value_list)
# now modify dict1 using dict3 instead of dict2
for outer_key, outer_value in dict1.items():
for inner_key_tuple, inner_value_list in outer_value.items():
lookup_key = (outer_key, str(inner_key_tuple[0]))
# search dict3 using the lookup_key.
# if not present, get will return an empty list
list_to_extend = dict3.get(lookup_key, [])
inner_value_list.extend(list_to_extend)
print(dict1)
Output
/tmp $ python test.py.py
{'AD': {(62, 'VMX', 'Barcelona', 'ES'): ['123', '567', '666', '345', '6754']}}
Based on the comments, since you wanted to know how to avoid one of the loops - here's an updated version
for k,v in dict1.items():
a = dict2.get(k)
if a is None or len(v) == 0:
continue
for k2,v2 in v.items():
for c2,a2 in a.items():
if str(k2[0]) == c2[4]:
v2.append(a2)
The for loops are placed correctly as long as the example goes.
What do you mean by unexpectedly?
Do you mean this?
{'AD': {(62, 'VMX', 'Barcelona', 'ES'): ['123', '567', '666', ['345', '6754']]}}
That extra array within the array?
Because if so, the answer would be to switch the .append() with a .extend()

If dict2 value = dict1 key, replace entire dict2 value with dict1 value

I have two dictionaries. In both dictionaries, the value of each key is a single list. If any element in any list in dictionary 2 is equal to a key of dictionary 1, I want to replace that element with the first element in that dictionary 1 list.
In other words, I have:
dict1 = {'IDa':['newA', 'x'], 'IDb':['newB', 'x']}
dict2 = {1:['IDa', 'IDb']}
and I want:
dict2 = {1:['newA', 'newB']}
I tried:
for ID1, news in dict1.items():
for x, ID2s in dict2.items():
for ID in ID2s:
if ID == ID1:
print ID1, 'match'
ID.replace(ID, news[0])
for k, v in dict2.items():
print k, v
and I got:
IDb match
IDa match
1 ['IDa', IDb']
So it looks like everything up to the replace method is working. Is there a way to make this work? To replace an entire string in a value-list with a string in another value-list?
Thanks a lot for your help.
Try this:
dict1 = {'IDa':['newA', 'x'], 'IDb':['newB', 'x']}
dict2 = {1:['IDa', 'IDb']}
for key in dict2.keys():
dict2[key] = [dict1[x][0] if x in dict1.keys() else x for x in dict2[key]]
print dict2
this will print:
{1: ['newA', 'newB']}
as required.
Explanation
dict.keys() gives us just the keys of a dictionary (i.e. just the left hand side of the colon). When we use for key in dict2.keys(), at present our only key is 1. If the dictionary was larger, it'd loop through all keys.
The following line uses a list comprehension - we know that dict2[key] gives us a list (the right side of the colon), so we loop through every element of the list (for x in dict2[key]) and return the first entry of the corresponding list in dict1 only if we can find the element in the keys of dict1 (dict1[x][0] if x in dict1.keys) and otherwise leave the element untouched ([else x]).
For example, if we changed our dictionaries to be the following:
dict1 = {'IDa':['newA', 'x'], 'IDb':['newB', 'x']}
dict2 = {1:['IDa', 'IDb'], 2:{'IDb', 'IDc'}}
we'd get the output:
{1: ['newA', 'newB'], 2: ['newB', 'IDc']}
because 'IDc' doesn't exist in the keys of dict1.
You could also use dictionary comprehensions, but I am not sure that they are working in Python 2.7, it may be limited to Python 3 :
# Python 3
dict2 = {k: [dict1.get(e, [e])[0] for e in v] for k,v in dict2.items()}
edit: I just checked, this is working in Python 2.7. However, dict2.items() should be replaced by dict2.iteritems() :
# Python 2.7
dict2 = {k: [dict1.get(e, [e])[0] for e in v] for k,v in dict2.iteritems()}
This was a fun one!
dict2[1] = [dict1[val][0] if val in dict1 else val for val in dict2[1]]
Or, here is the same logic without list comprehension:
new_dict = {1: []}
for val in dict2[1]:
if val in dict1:
new_dict[1].append(dict1[val][0])
else:
new_dict[1].append(val)
dict2 = new_dict

Comparing list values between two dictionaries that have no matching keys

I have two dictionaries where they keys won't match, but values will. All values in each dictionary contain 3 list items as ints.
dict1 = {'red':[1,2,3],'blue':[2,3,4],'orange':[3,4,5]}
dict2 = {'green':[3,4,5],'yellow':[2,3,4],'red':[5,2,6]}
I would like to compare each list and find which two keys have matching value lists. In this case "blue" and "yellow" match, as well as "green" and "orange".
I took a look at this thread but was not able to get it to work, and I'm not exactly sure I'm asking the same thing: comparing two dictionaries with list type values
I haven't worked with dictionaries before and am not really sure I understand list comprehensions yet, either. (A lot of posts seem to use them)
Just keep it nice and simple:
dict1 = {'red':[1,2,3],'blue':[2,3,4],'orange':[3,4,5]}
dict2 = {'green':[3,4,5],'yellow':[2,3,4],'red':[5,2,6]}
matches = []
for key1 in dict1:
for key2 in dict2:
if dict1[key1] == dict2[key2]:
matches.append((key1, key2))
print(matches)
Output:
[('blue', 'yellow'), ('orange', 'green')]
You can use a list comprehension (which is just a shortcut for "for loops"):
matching = [(k1, k2) for k1 in dict1 for k2 in dict2 if dict1[k1] == dict2[k2]]
print matching
# [('blue', 'yellow'), ('orange', 'green')]
For any case if you don't understand Julien's answer, this doing the same thing.
dict1 = {'red':[1,2,3],'blue':[2,3,4],'orange':[3,4,5]}
dict2 = {'green':[3,4,5],'yellow':[2,3,4],'red':[5,2,6]}
for k1,v1 in dict1.items(): #each key and value in dict1
for k2,v2 in dict2.items(): #each key and value in dict2
if v1 == v2: #if values match
print (k1,k2) #print their keys

Updating a dictionary

I have created three dictionaries-dict1, dict2, and dict2. I want to update dict1 with dict2 first, and resulting dictionary with dict3. I am not sure why they are not adding up.
def wordcount_directory(directory):
dict = {}
filelist=[os.path.join(directory,f) for f in os.listdir(directory)]
dicts=[wordcount_file(file) for file in filelist]
dict1=dicts[0]
dict2=dicts[1]
dict3=dicts[2]
for k,v in dict1.iteritems():
if k in dict2.keys():
dict1[k]+=1
else:
dict1[k]=v
for k1,v1 in dict1.iteritems():
if k1 in dict3.keys():
dict1[k1]+=1
else:
dict1[k1]=v1
return dict1
print wordcount_directory("C:\\Users\\Phil2040\\Desktop\\Word_count")
Maybe I am not understanding you question right, but are you trying to add all the values from each of the dictionaries together into one final dictionary? If so:
dict1 = {'a': 1, 'b': 2, 'c': 3}
dict2 = {'b': 5, 'c': 1, 'd': 9}
dict3 = {'d': 1, 'e': 7}
def add_dict(to_dict, from_dict):
for key, value in from_dict.iteritems():
to_dict[key] = to_dict.get(key, 0) + value
result = dict(dict1)
add_dict(result, dict2)
add_dict(result, dict3)
print result
This yields: {'a': 1, 'c': 4, 'b': 7, 'e': 7, 'd': 10}
It would be really helpful to post what the expected outcome should be for your question.
EDIT:
For an arbitrary amount of dictionaries:
result = dict(dicts[0])
for dict_sum in dicts[1:]:
add_dict(result, dict_sum)
print(result)
If you really want to fix the code from your original question in the format it is in:
You are using dict1[k]+=1 when you should be performing dict1[k]+=dict2.get(k, 0).
The introduction of get removes the need to check for its existence with an if statement.
You need to iterate though dict2 and dict3 to introduce new keys from them into dict1
(not really a problem, but worth mentioning) In the if statement to check if the key is in the dictionary, it is recommended to simply the operation to if k in dict2: (see this post for more details)
With the amazing built-in library found by #DisplacedAussie, the answer can be simplified even further:
from collections import Counter
print(Counter(dict1) + Counter(dict2) + Counter(dict3))
The result yields: Counter({'d': 10, 'b': 7, 'e': 7, 'c': 4, 'a': 1})
The Counter object is a sub-class of dict, so it can be used in the same way as a standard dict.
Hmmm, here a simple function that might help:
def dictsum(dict1, dict2):
'''Modify dict1 to accumulate new sums from dict2
'''
k1 = set(dict1.keys())
k2 = set(dict2.keys())
for i in k1 & k2:
dict1[i] += dict2[i]
for i in k2 - k1:
dict1[i] = dict2[i]
return None
... for the intersection update each by adding the second value to the existing one; then for the difference add those key/value pairs.
With that defined you'd simple call:
dictsum(dict1, dict2)
dictsum(dict1, dict3)
... and be happy.
(I will note that functions modify the contents of dictionaries in this fashion are not all that common. I'm returning None explicitly to follow the convention established by the list.sort() method ... functions which modify the contents of a container, in Python, do not normally return copies of the container).
If I understand your question correctly, you are iterating on the wrong dictionary. You want to iterate over dict2 and update dict1 with matching keys or add non-matching keys to dict1.
If so, here's how you need to update the for loops:
for k,v in dict2.iteritems(): # Iterate over dict2
if k in dict1.keys():
dict1[k]+=1 # Update dict1 for matching keys
else:
dict1[k]=v # Add non-matching keys to dict1
for k1,v1 in dict3.iteritems(): # Iterate over dict3
if k1 in dict1.keys():
dict1[k1]+=1 # Update dict1 for matching keys
else:
dict1[k1]=v1 # Add non-matching keys to dict1
I assume that wordcount_file(file) returns a dict of the words found in file, with each key being a word and the associated value being the count for that word. If so, your updating algorithm is wrong. You should do something like this:
keys1 = dict1.keys()
for k,v in dict2.iteritems():
if k in keys1:
dict1[k] += v
else:
dict1[k] = v
If there's a lot of data in these dicts you can make the key lookup faster by storing the keys in a set:
keys1 = set(dict1.keys())
You should probably put that code into a function, so you don't need to duplicate the code when you want to update dict1 with the data in dict3.
You should take a look at collections.Counter, a subclass of dict that supports counting; using Counters would simplify this task considerably. But if this is an assignment (or you're using Python 2.6 or older) you may not be able to use Counters.

Categories

Resources