I have a python dictionary dict1 with more than 20,000 keys and I want to update it with another dictionary dict2. The dictionaries look like this:
dict1
key11=>[value11]
key12=>[value12]
...
...
keyxyz=>[value1x] //common key
...... so on
dict2
key21=>[value21]
key22=>[value22]
...
...
keyxyz=>[value2x] // common key
........ so on
If I use
dict1.update(dict2)
then the keys of dict1 which are similar to keys of dict2 will have their values overwritten by values of dict2. What I want is if a key is already present in dict1 then the value of that key in dict2 should be appended to value of dict1. So
dict1.conditionalUpdate(dict2)
should result in
dict1
key11=>[value11]
key12=>[value12]
key21=>[value21]
key22=>[value22]
...
...
keyxyz=>[value1x,value2x]
A naive method would be iterating over keys of dict2 for each key of dict1 and insert or update keys. Is there a better method? Does python support a built in data structure that supports this kind of functionality?
Use defaultdict from the collections module.
>>> from collections import defaultdict
>>> dict1 = {1:'a',2:'b',3:'c'}
>>> dict2 = {1:'hello', 4:'four', 5:'five'}
>>> my_dict = defaultdict(list)
>>> for k in dict1:
... my_dict[k].append(dict1[k])
...
>>> for k in dict2:
... my_dict[k].append(dict2[k])
...
>>> my_dict[1]
['a', 'hello']
This is actually pretty simple to do using a dict comprehension and itertools.groupby():
dict1 = {1: 1, 2: 2, 3: 3, 4: 4}
dict2 = {5: 6, 7: 8, 1: 1, 2: 2}
from itertools import groupby, chain
from operator import itemgetter
sorted_items = sorted(chain(dict1.items(), dict2.items()))
print({key: [value[1] for value in values] for key, values in groupby(sorted_items, itemgetter(0))})
Gives us:
{1: [1, 1], 2: [2, 2], 3: [3], 4: [4], 5: [6], 7: [8]}
Naturally, this creates a new dict, but if you need to update the first dict, you can do that trivially by updating with the new one. If your values are already lists, this may need some minor modification (but I presume you were doing that for the sake of the operation, in which case, there is no need).
Naturally, if you are using Python 2.x, then you will want to use dict.viewitems() or dict.iteritems() over dict.items(). If you are using a version of Python prior to dict comprehensions, then you could use dict((key , value) for ...) instead.
Another method without importing anything, just with the regular Python dictionary:
>>> dict1 = {1:'a',2:'b',3:'c'}
>>> dict2 = {1:'hello', 4:'four', 5:'five'}
>>> for k in dict2:
... dict1[k] = dict1.get(k,"") + dict2.get(k)
...
>>> dict1
{1: 'ahello', 2: 'b', 3: 'c', 4: 'four', 5: 'five'}
>>>
dict1.get(k,"") returns the value associated to k if it exists or an empty string otherwise, and then append the content of dict2.
Related
I want to make know if there is a command that can do this:
>>>A=dict()
>>>A[1]=3
>>>A
{1:3}
>>>A[1].add(5) #This is the command that I don't know if exists.
>>>A
{1:(3,5)}
I mean, add another value to the same key without quiting the old value added.
It is possible to do this?
You could make the dictionary values into lists:
>>> A = dict()
>>> A[1] = [3]
>>> A
{1: [3]}
>>> A[1].append(5) # Add a new item to the list
>>> A
{1: [3, 5]}
>>>
You may also be interested in dict.setdefault, which has functionality similar to collections.defaultdict but without the need to import:
>>> A = dict()
>>> A.setdefault(1, []).append(3)
>>> A
{1: [3]}
>>> A.setdefault(1, []).append(5)
>>> A
{1: [3, 5]}
>>>
A defaultdict of type list will create an empty list in case you access a key that does not exist in the dictionary so far. This often leads to quite elegant code.
>>> from collections import defaultdict
>>> d = defaultdict(list)
>>> d[1].append(3)
>>> d[1].append(2)
>>> d
defaultdict(<type 'list'>, {1: [3, 2]})
Using a defaultdict eliminates the "special case" of the initial insert.
from collections import defaultdict
A = defaultdict(list)
for num in (3,5):
A[1].append(num)
Like others pointed out, store the values in a list, but remember to check if the key is in the dictionary to determine whether you need to append or create a new list for that key...
A = dict()
if key in A: A[key].append(value)
else: A[key] = [value]
I'm working on an assignment. Is there anyway a dictionary can have duplicate keys and hold the same or different values. Here is an example of what i'm trying to do:
dict = {
'Key1' : 'Helo', 'World'
'Key1' : 'Helo'
'Key1' : 'Helo', 'World'
}
I tried doing this but when I associate any value to key1, it gets added to the same key1.
Is this possible with a dictionary? If not what other data structure I can use to implement this process?
Use dictionaries of lists to hold multiple values.
One way to have multiple values to a key is to use a dictionary of lists.
x = { 'Key1' : ['Hello', 'World'],
'Key2' : ['Howdy', 'Neighbor'],
'Key3' : ['Hey', 'Dude']
}
To get the list you want (or make a new one), I recommend using setdefault.
my_list = x.setdefault(key, [])
Example:
>>> x = {}
>>> x['abc'] = [1,2,3,4]
>>> x
{'abc': [1, 2, 3, 4]}
>>> x.setdefault('xyz', [])
[]
>>> x.setdefault('abc', [])
[1, 2, 3, 4]
>>> x
{'xyz': [], 'abc': [1, 2, 3, 4]}
Using defaultdict for the same functionality
To make this even easier, the collections module has a defaultdict object that simplifies this. Just pass it a constructor/factory.
from collections import defaultdict
x = defaultdict(list)
x['key1'].append(12)
x['key1'].append(13)
You can also use dictionaries of dictionaries or even dictionaries of sets.
>>> from collections import defaultdict
>>> dd = defaultdict(dict)
>>> dd
defaultdict(<type 'dict'>, {})
>>> dd['x']['a'] = 23
>>> dd
defaultdict(<type 'dict'>, {'x': {'a': 23}})
>>> dd['x']['b'] = 46
>>> dd['y']['a'] = 12
>>> dd
defaultdict(<type 'dict'>, {'y': {'a': 12}, 'x': {'a': 23, 'b': 46}})
I think you want collections.defaultdict:
from collections import defaultdict
d = defaultdict(list)
list_of_values = [['Hello', 'World'], 'Hello', ['Hello', 'World']]
for v in list_of_values:
d['Key1'].append(v)
print d
This will deal with duplicate keys, and instead of overwriting the key, it will append something to that list of values.
Keys are unique to the data. Consider using some other value for a key or consider using a different data structure to hold this data.
for example:
don't use a persons address as a unique key because several people might live there.
a person's social security number or a drivers license is a much better unique id of a person.
you can create your own id to force it to be unique.
So I realized that
dict1.update(dict2)
replaces values of dict2 with dict1 if the key exists in both the dictionaries. Is there any way to add the values of dict2 to dict1 directly if the key is present instead of looping around the key,value pairs
You say you want to add the values, but not what type they are. If they are numeric, you may be able to use collections.Counter instead of dict
>>> from collections import Counter
>>> a = Counter({'a':1, 'b':2})
>>> b = Counter({'a':5.4, 'c':6})
>>> a + b
Counter({'a': 6.4, 'c': 6, 'b': 2})
My question is: How can I get a dictionary key using a dictionary value?
d={'dict2': {1: 'one', 2: 'two'}, 'dict1': {3: 'three', 4: 'four'}}
I want to get dict2 the key of the key of two.
Thanks.
Here's a recursive solution that can handle arbitrarily nested dictionaries:
>>> import collections
>>> def dict_find_recursive(d, target):
... if not isinstance(d, collections.Mapping):
... return d == target
... else:
... for k in d:
... if dict_find_recursive(d[k], target) != False:
... return k
... return False
It's not as efficient in the long run as a "reverse dictionary," but if you aren't doing such reverse searches frequently, it probably doesn't matter. (Note that you have to explicitly compare the result of dict_find_recursive(d[k], target) to False because otherwise falsy keys like '' cause the search to fail. In fact, even this version fails if False is used as a key; a fully general solution would use a unique sentinel object() to indicate falseness.)
A few usage examples:
>>> d = {'dict1': {3: 'three', 4: 'four'}, 'dict2': {1: 'one', 2: 'two'}}
>>> dict_find_recursive(d, 'two')
'dict2'
>>> dict_find_recursive(d, 'five')
False
>>> d = {'dict1': {3: 'three', 4: 'four'}, 'dict2': {1: 'one', 2: 'two'},
'dict3': {1: {1:'five'}, 2: 'six'}}
>>> dict_find_recursive(d, 'five')
'dict3'
>>> dict_find_recursive(d, 'six')
'dict3'
If you want to reverse an arbitrarily nested set of dictionaries, recursive generators are your friend:
>>> def dict_flatten(d):
... if not isinstance(d, collections.Mapping):
... yield d
... else:
... for value in d:
... for item in dict_flatten(d[value]):
... yield item
...
>>> list(dict_flatten(d))
['three', 'four', 'five', 'six', 'one', 'two']
The above simply lists all the values in the dictionary that aren't mappings. You can then map each of those values to a key like so:
>>> def reverse_nested_dict(d):
... for k in d:
... if not isinstance(d[k], collections.Mapping):
... yield (d[k], k)
... else:
... for item in dict_flatten(d[k]):
... yield (item, k)
...
This generates a iterable of tuples, so no information is lost:
>>> for tup in reverse_nested_dict(d):
... print tup
...
('three', 'dict1')
('four', 'dict1')
('five', 'dict3')
('six', 'dict3')
('one', 'dict2')
('two', 'dict2')
If you know that all your non-mapping values are hashable -- and if you know they are unique, or if you don't care about collisions -- then just pass the resulting tuples to dict():
>>> dict(reverse_nested_dict(d))
{'six': 'dict3', 'three': 'dict1', 'two': 'dict2', 'four': 'dict1',
'five': 'dict3', 'one': 'dict2'}
If you don't want to reverse the dictionary, here's another possible solution:
def get_key_from_value(my_dict, v):
for key,value in my_dict.items():
if value == v:
return key
return None
>>> d = {1: 'one', 2: 'two'}
>>> get_key_from_value(d,'two')
2
The following will create a reverse dictionary for the two-level example:
d={'dict2': {1: 'one', 2: 'two'}, 'dict1': {3: 'three', 4: 'four'}}
r = {}
for d1 in d:
for d2 in d[d1]:
r[d[d1][d2]] = d1
The result:
>>> r
{'four': 'dict1', 'three': 'dict1', 'two': 'dict2', 'one': 'dict2'}
I don't know about the best solution, but one possibility is reversing the dictionary (so that values becomes keys) and then just doing a normal key lookup. This will reverse a dictionary:
forward_dict = { 'key1': 'val1', 'key2': 'val2'}
reverse_dict = dict([(v,k) for k,v in forward_dict.items()])
So given "val1", I can just do:
reverse_dict["val1"]
to find the corresponding key. There are obvious problems with this solution -- for example, if your values aren't unique, you're going to lose some information.
Write code to reverse the dictionary (i.e. create a new dictionary that maps the values of the old one to the keys of the old one).
Since you seem to be dealing with nested dictionaries, this will obviously be trickier. Figure out the least you need to get your problem solved and code that up (i.e. don't create a solution that will work arbitrary depths of nesting if your problem only deals with dicts in dicts which in turn don't have any dicts)
To handle the nested dictionaries I would do just as senderle's answer states.
However if in the future it does not contain nested dictionaries, be very careful doing a simple reversal. By design the dictionary keys are unique, but the values do not have this requirement.
If you have values that are the same for multiple keys, when reversing the dictionary you will lose all but one of them. And because dictionaries are not sorted, you could lose different data arbitrarily.
Example of reversal working:
>>> d={'dict1': 1, 'dict2': 2, 'dict3': 3, 'dict4': 4}
>>> rd = dict([(v,k) for k,v in d.items()])
>>> print d
{'dict4': 4, 'dict1': 1, 'dict3': 3, 'dict2': 2}
>>> print rd
{1: 'dict1', 2: 'dict2', 3: 'dict3', 4: 'dict4'}
Example of reversal failure: Note that dict4 is lost
>>> d={'dict1': 1, 'dict2': 4, 'dict3': 3, 'dict4': 4}
>>> rd = dict([(v,k) for k,v in d.items()])
>>> print d
{'dict4': 4, 'dict1': 1, 'dict3': 3, 'dict2': 4}
>>> print rd
{1: 'dict1', 3: 'dict3', 4: 'dict2'}
here's an example nobody thinks about: (could be used similarly)
raw_dict = { 'key1': 'val1', 'key2': 'val2', 'key3': 'val1' }
new_dict = {}
for k,v in raw_dict.items():
try: new_dict[v].append(k)
except: new_dict[v] = [k]
result:
>>> new_dict
{'val2': ['key2'], 'val1': ['key3', 'key1']}
maybe not the best of methods, but it works for what I need it for.
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
syntax to insert one list into another list in python
How could be the syntax for creating a dictionary into another dictionary in python
You can declare a dictionary inside a dictionary by nesting the {} containers:
d = {'dict1': {'foo': 1, 'bar': 2}, 'dict2': {'baz': 3, 'quux': 4}}
And then you can access the elements using the [] syntax:
print d['dict1'] # {'foo': 1, 'bar': 2}
print d['dict1']['foo'] # 1
print d['dict2']['quux'] # 4
Given the above, if you want to add another dictionary to the dictionary, it can be done like so:
d['dict3'] = {'spam': 5, 'ham': 6}
or if you prefer to add items to the internal dictionary one by one:
d['dict4'] = {}
d['dict4']['king'] = 7
d['dict4']['queen'] = 8
dict1 = {}
dict1['dict2'] = {}
print dict1
>>> {'dict2': {},}
this is commonly known as nesting iterators into other iterators I think
Do you want to insert one dictionary into the other, as one of its elements, or do you want to reference the values of one dictionary from the keys of another?
Previous answers have already covered the first case, where you are creating a dictionary within another dictionary.
To re-reference the values of one dictionary into another, you can use dict.update:
>>> d1 = {1: [1]}
>>> d2 = {2: [2]}
>>> d1.update(d2)
>>> d1
{1: [1], 2: [2]}
A change to a value that's present in both dictionaries will be visible in both:
>>> d1[2].append('appended')
>>> d1
{1: [1], 2: [2, 'appended']}
>>> d2
{2: [2, 'appended']}
This is the same as copying the value over or making a new dictionary with it, i.e.
>>> d3 = {1: d1[1]}
>>> d3[1].append('appended from d3')
>>> d1[1]
[1, 'appended from d3']