Finding a key-value pair present only in the first dictionary - python

Two dictionaries:
dict1 = {'firstvalue':1, 'secondvalue':2, 'fourthvalue':4}
dict2 = {'firstvalue':1, 'thirdvalue':3, 'fourthvalue':5}
I get set(['secondvalue']) as a result upon doing:
dict1.viewkeys() - dict2
I need {'secondvalue':2} as a result.
When I use set, and then do the - operation, it does not give the desired result as it consists of {'fourthvalue:4} as well.
How could I do it?

The problem with - is that (in this context) it is an operation of dict_keys and thus the results will have no values. Using - with viewitems() does not work, either, as those are tuples, i.e. will compare both keys and values.
Instead, you can use a conditional dictionary comprehension, keeping only those keys that do not appear in the second dictionary. Other than Counter, this also works in the more general case, where the values are not integers, and with integer values, it just checks whether a key is present irrespective of the value that is accociated with it.
>>> dict1 = {'firstvalue':1, 'secondvalue':2, 'fourthvalue':4}
>>> dict2 = {'firstvalue':1, 'thirdvalue':3, 'fourthvalue':5}
>>> {k: v for k, v in dict1.items() if k not in dict2}
{'secondvalue': 2}

IIUC and providing a solution to Finding a key-value pair present only in the first dictionary as specified, you could take a set from the key/value pairs as tuples, subtract both sets and construct a dictionary from the result:
dict(set(dict1.items()) - set(dict2.items()))
# {'fourthvalue': 4, 'secondvalue': 2}

Another simple variation with set difference:
res = {k: dict1[k] for k in dict1.keys() - dict2.keys()}

Python 2.x:
dict1 = {'firstvalue':1, 'secondvalue':2, 'fourthvalue':4}
dict2 = {'firstvalue':1, 'thirdvalue':3, 'fourthvalue':5}
keys = dict1.viewkeys() - dict2.viewkeys()
print ({key:dict1[key] for key in keys})
output:
{'secondvalue': 2}

Related

How to switch between keys and values in python dictionary in place (without changing it's location in memory)

i was asked to write a code including a function- reverse_dict_in_place(d)
which switches between keys and values of the inputed dictionary
without changing the dictionary's location in memory (in place).
however, testing it with id() function shows that all my solutions do change dictionaries memory location..
def reverse_dict_in_place(d):
d={y:x for x,y in d.items()}
return d
Alternative to current ones which allows values to be same as keys. Works in mostly the same way though, however once again no two values may be the same.
def reverse_dict_in_place(d):
copy = d.copy().items()
d.clear()
for k, v in copy:
d[v] = k
return d
>>> x = {0: 1, 1: 2}
>>> y = reverse_dict_in_place(x)
>>> id(x) == id(y)
True
>>>
Some assumptions for this to work (thanks to all the users who pointed these out):
There are no duplicate values
There are no non-hashable values
There are no values that are also keys
If you're comfortable with those assumption then I think this should work:
def reverse_dict_in_place(d):
for k,v in d.items():
del d[k]
d[v] = k
return d
Extending on Gad suggestion, you could use dict comprehension:
reversed = {v: k for k, v in d.items()}
Where d is a dict, and the same assumptions apply:
There are no duplicate values
There are no non-hashable values
There are no values that are also keys
This would not work, without modification, for nested dicts.
Note: #NightShade has posted a similar answer as my below answer, earlier than I posted.
You can try this:
def reverse_dict_in_place(d):
d_copy = d.copy()
d.clear()
for k in d_copy:
d[d_copy[k]] = k
This would work even if one of the dictionary's values happens to also be a key (as tested out below)
Testing it out:
my_dict = {1:1, 2:'two', 3:'three'}
reverse_dict_in_place(my_dict)
print (my_dict)
Output:
{1: 1, 'two': 2, 'three': 3}

Use A Single Line To Loop Two Dictionaries To Create List

I have looked at several threads similar but unable to get a workable solution. I am looping (2) dictionaries trying to create a single list from the values of one based on the keys of another. I have it done with for loops but looking to use a single line if possible. My code with for loops
for k, v in dict1.items():
for value in dict2[k]:
temp.append(value)
On the first loop thru the temp list would be and is from above code:
[16,18,20,22,24,26]
I then use min to get the min value of the list. Now I want to condense the for loop to a one liner. I have put together
temp=[dict2.values() for k in dict1.keys() if k in dict2.keys()]
When executed, instead of temp being a single list for the k that exist in the dict1, I get a list of list for all the values from all dict2.
[[16,18,20,22,24,26], [12,16,18,20,22,24], [16,18,22,26,30,32]]
It seems to be ignoring the if statement. I know my dict1 has only 1 key in this situation and I know the 1 key exist in the dict2. Is my one liner wrong?
Input Values for dictionaries:
dict1={'table1':[16,18,20,22,24,26]}
dict2={'table1':[16,18,20,22,24,26],'table2': [12,16,18,20,22,24], 'table3': [16,18,22,26,30,32]}
You can iterate through one dictionary checking for matching keys and create a list of lists. Use chain.from_iterable to flatten list and call min():
from itertools import chain
dict1 = {'table1': [16,18,20,22,24,26]}
dict2 = {'table1': [16,18,20,22,24,26], 'table2': [12,16,18,20,22,24], 'table3': [16,18,22,26,30,32]}
temp = [dict2[k] for k in dict1 if k in dict2]
print(min(chain.from_iterable(temp)))
# 16
The reason why your list comprehension does not work:
It looks like dict2 has 3 key-value pairs, and the values are [16,18,20,22,24,26], [12,16,18,20,22,24]and [16,18,22,26,30,32]. What you're doing in your list comprehension translates to
for k in dict1.keys():
if k in dict2.keys():
temp.append(dict2.values())
So if dict1has, let's say, 3 keys, this for loop will repeat 3 times. Because, as you said in a comment above, only one key is shared between dict1and dict2, the if statement only is True once, so all items of dict2.values() will be appended to temponce. What you want to do, if i got that right, is to append all items INSIDE one of the values of dict2, namely the one assigned to the one key that the two dicts share. Your idea was pretty close, you just have to add one little thing. As a one liner, it would look like this:
temp = [x for x in dict2[k] for k in dict1.keys() if k in dict2.keys()]
or, differently:
temp = [dict2[k] for k in set(dict1.keys()).intersection(set(dict2.keys()))]
You can use the operator itemgetter():
from operator import itemgetter
from itertools import chain
dict1 = {'table1': [16,18,20,22,24,26], 'table2': [12,16,18,20,22,24]}
dict2 = {'table1': [16,18,20,22,24,26], 'table2': [12,16,18,20,22,24], 'table3': [16,18,22,26,30,32]}
common_keys = set(dict1).intersection(dict2)
sublists = itemgetter(*common_keys)(dict2)
if len(common_keys) == 1:
max_val = max(sublists)
else:
max_val = max(chain.from_iterable(sublists))
print(max_val)
# 26

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

Returning unique elements from values in a dictionary

I have a dictionary like this :
d = {'v03':["elem_A","elem_B","elem_C"],'v02':["elem_A","elem_D","elem_C"],'v01':["elem_A","elem_E"]}
How would you return a new dictionary with the elements that are not contained in the key of the highest value ?
In this case :
d2 = {'v02':['elem_D'],'v01':["elem_E"]}
Thank you,
I prefer to do differences with the builtin data type designed for it: sets.
It is also preferable to write loops rather than elaborate comprehensions. One-liners are clever, but understandable code that you can return to and understand is even better.
d = {'v03':["elem_A","elem_B","elem_C"],'v02':["elem_A","elem_D","elem_C"],'v01':["elem_A","elem_E"]}
last = None
d2 = {}
for key in sorted(d.keys()):
if last:
if set(d[last]) - set(d[key]):
d2[last] = sorted(set(d[last]) - set(d[key]))
last = key
print d2
{'v01': ['elem_E'], 'v02': ['elem_D']}
from collections import defaultdict
myNewDict = defaultdict(list)
all_keys = d.keys()
all_keys.sort()
max_value = all_keys[-1]
for key in d:
if key != max_value:
for value in d[key]:
if value not in d[max_value]:
myNewDict[key].append(value)
You can get fancier with set operations by taking the set difference between the values in d[max_value] and each of the other keys but first I think you should get comfortable working with dictionaries and lists.
defaultdict(<type 'list'>, {'v01': ['elem_E'], 'v02': ['elem_D']})
one reason not to use sets is that the solution does not generalize enough because sets can only have hashable objects. If your values are lists of lists the members (sublists) are not hashable so you can't use a set operation
Depending on your python version, you may be able to get this done with only one line, using dict comprehension:
>>> d2 = {k:[v for v in values if not v in d.get(max(d.keys()))] for k, values in d.items()}
>>> d2
{'v01': ['elem_E'], 'v02': ['elem_D'], 'v03': []}
This puts together a copy of dict d with containing lists being stripped off all items stored at the max key. The resulting dict looks more or less like what you are going for.
If you don't want the empty list at key v03, wrap the result itself in another dict:
>>> {k:v for k,v in d2.items() if len(v) > 0}
{'v01': ['elem_E'], 'v02': ['elem_D']}
EDIT:
In case your original dict has a very large keyset [or said operation is required frequently], you might also want to substitute the expression d.get(max(d.keys())) by some previously assigned list variable for performance [but I ain't sure if it doesn't in fact get pre-computed anyway]. This speeds up the whole thing by almost 100%. The following runs 100,000 times in 1.5 secs on my machine, whereas the unsubstituted expression takes more than 3 seconds.
>>> bl = d.get(max(d.keys()))
>>> d2 = {k:v for k,v in {k:[v for v in values if not v in bl] for k, values in d.items()}.items() if len(v) > 0}

removing key value pairs by matching values python

I am searching for periods "." in a dictionary and trying to delete the key/value pair if I find it
if "." in dict.values():
#delete key, value pair from the dictionary
I am sure this is very simple but I cannot seem to locate an explanation.
Thanks for your help.
Create a new dictionary without those unwanted values using dictionary comprehension. Here is an example of how to do it:
>>> old_dict = {'one': '.', 'two': 2, 'three':3, 'four':'.'}
>>> new_dict = {k:v for k,v in old_dict.iteritems() if not v == '.'}
>>> new_dict
{'three': 3, 'two': 2}
using iteritems instead of items avoids creating an intermediate list and improves performance.
If you don't want to copy your dictionary, (for example if the dictionary is large, or you have a reference to it elsewhere) then you should do it this way:
ks = [k for k in d if d[k]=='.']
for k in ks:
d.pop(k)
Create your list of keys to be removed ahead of time as shown above. You don't want to modify your dictionary while iterating over it.

Categories