Reputation: 875
I am using Python 2.7 with Windows 7.
I have a dictionary and would like to remove values that correspond to (key, value) pairs from another dictionary.
For example, I have a dictionary t_dict
. I would like to remove corresponding (key,value) pairs that are in the dictionary values_to_remove
so that I end up with dictionary final_dict
t_dict = {
'a': ['zoo', 'foo', 'bar'],
'c': ['zoo', 'foo', 'yum'],
'b': ['tee', 'dol', 'bar']
}
values_to_remove = {
'a': ['zoo'],
'b': ['dol', 'bar']
}
# remove values here
print final_dict
{
'a': ['foo', 'bar'],
'c': ['zoo', 'foo', 'yum'],
'b': ['tee']
}
I have looked at similar pages on SO and the python dictionaries doc but cannot find anything to solve this specific problem:
https://docs.python.org/2/library/stdtypes.html#dict
How to remove dictionaries with duplicate values from a nested dictionary
How to remove a key from a python dictionary?
EDIT
There cannot be duplicate values in t_dict
per key. For example there will never be
t_dict['a'] = ['zoo','zoo','foo','bar']
Upvotes: 1
Views: 182
Reputation: 155323
Since duplicates aren't possible, it might make sense to store the values as a set
, not a list
. If you can use a set
for t_dict
, the removal process is both faster and simpler to write (even faster if values_to_remove
uses set
or frozenset
too):
for k, toremove in values_to_remove.viewitems():
t_dict.get(k, set()).difference_update(toremove)
Use the above if values_to_remove
expected to be small, or if t_dict
is smaller, you could switch to the following to avoid the temporary set()
s (the empty tuple
is a singleton, so it costs nothing to use it with dict.get
):
for k, v in t_dict.viewitems():
v.difference_update(values_to_remove.get(k, ()))
Final option is the overly clever approach that removes the need for using .get
at all by only processing keys that appear in both dict
s (using -=
requires both dict
s to use set
for values to be shorter/faster, you could go back to difference_update
if you want to allow non-set
s for values_to_remove
's values):
for k in (t_dict.viewkeys() & values_to_remove.viewkeys()):
t_dict[k] -= values_to_remove[k]
Upvotes: 3
Reputation: 5508
When you don't want to have the duplicated elements in your dict, and the order also not so important, why don't use set
as you dic value?
t_dict = {
'a': set(['zoo', 'foo', 'bar']),
'c': set(['zoo', 'foo', 'yum']),
'b': set(['tee', 'dol', 'bar'])
}
values_to_remove = {
'a': set(['zoo']),
'b': set(['dol', 'bar'])
}
for k,v in values_to_remove.iteritems():
t_dict[k] = t_dict[k]-v
print t_dict
>>>{'a': set(['foo', 'bar']), 'c': set(['foo', 'yum', 'zoo']), 'b': set(['tee'])}
If the Order important for you, you can also use the OrderedSet like @sparkandshine in comment suggested. http://orderedset.readthedocs.io/en/latest/
from ordered_set import OrderedSet
t_dict = {
'a': OrderedSet(['zoo', 'foo', 'bar']),
'c': OrderedSet(['zoo', 'foo', 'yum']),
'b': OrderedSet(['tee', 'dol', 'bar'])
}
values_to_remove = {
'a': OrderedSet(['zoo']),
'b': OrderedSet(['dol', 'bar'])
}
for k,v in values_to_remove.iteritems():
t_dict[k] = t_dict[k]-v
print t_dict
>>>{'a': OrderedSet(['foo', 'bar']), 'c': OrderedSet(['zoo', 'foo', 'yum']), 'b': OrderedSet(['tee'])}
Upvotes: 1
Reputation: 17997
Try this,
for k, v in t_dict.items():
for item in values_to_remove.get(k, ()):
v.remove(item)
# Output
{'a': ['foo', 'bar'], 'c': ['zoo', 'foo', 'yum'], 'b': ['tee']}
Upvotes: 5
Reputation: 3607
for key,values in values_to_remove.items():
for value in values:
if key in t_dict and value in t_dict[key]:
t_dict[key].pop(t_dict[key].index(value))
Upvotes: 2