Prachi
Prachi

Reputation: 554

How to append one python dictionary to another while preserving their key-values as it is?

How to append one python dictionary to another in such a way that if the distinct keys in both have overlapping values then data is not modified but preserved as it is? Also this has to be done inside a for loop which will return a new dictionary with every iteration. So the idea is to create one final master dictionary containing all the dictionaries returned by the loop.

Something like:

finaldict = dict()
for - some loop condition:
    dict1 = function-call()
    finaldict = finaldict + dict1
access 'finaldict' outside the loop. 'finaldict' should now contain all the returned 'dict1's.

The way the 2 dictionaries are required to concatenate is like:

finaldict = {22: [7, 9, 8]}
dict1 = {23: [7, 9, 8, 6, 12]}

and desired result is:

finaldict = {22: [7, 9, 8], 23: [7, 9, 8, 6, 12]}

How can this be achieved in the fastest way possible in python?

Upvotes: 3

Views: 10709

Answers (3)

Blckknght
Blckknght

Reputation: 104792

If you're seeing the list values change, it's likely that your function is always returning the same list object, not separate lists on separate times. Even if you kept the lists outside of the dictionary you're merging, you'd find the old ones didn't have the same values in them you expected.

You can see that kind of behavior with this code:

_lst = [] # this is an implementation detail of the function below

def foo():
    """returns a steadily longer list of "foo" strings"""
    _lst.append('foo')
    return _lst

print(foo()) # prints ['foo']
print(foo()) # prints ['foo', 'foo'], all as expected so far

x = foo()
print(x)     # prints ['foo', 'foo', 'foo'], fine

y = foo()
print(y)     # prints ['foo', 'foo', 'foo', foo'], fine here too
print(x)     # prints ['foo', 'foo', 'foo', foo'], unexpectedly changed!

You might be surprised how the value of x changed when foo was called again to assign y. But that's only if you don't realize that x and y are both references to the same list object _lst (something you might not know if you don't know how the foo function is implemented).

In your code, your function is returning the same list in the same way that foo is (though with a dictionary wrapped around it, so it's less obvious). If you control the function, you might be able to change it so that it returns a new list each time. In my example, that might look like:

def foo():
    _lst.append('foo')
    return list(_lst)    # return a shallow copy of the list!

Your code would probably be a bit more complicated, but probably not by much. Just make sure you make a new list for each dictionary you return.

On the other hand, if you can't modify the function (perhaps because it's part of a library or something), you can instead make the copy yourself, when you go to merge the dictionaries.

finaldict = dict()
while some_condition():
    dict1 = function_call()
    finaldict.update((key, list(value)) for key, value in dict1.items())

The generator expression we're passing to dict.update yields key, value tuples, but the values are shallow copies of the lists in the dictionary we got from function_call.

Upvotes: 2

iris
iris

Reputation: 381

A simple solution (Python3.5) with prefix operator ** used for unpacking dictionaries by key-value (PEP 448).

>>> {**dict1, **finaldict}
{23: [7, 9, 8, 6, 12], 22: [7, 9, 8]}

Upvotes: 1

Rajat Mishra
Rajat Mishra

Reputation: 3780

you can do using update function:

In [21]: finaldict = {22: [7, 9, 8]}
    ...: dict1 = {23: [7, 9, 8, 6, 12]}

In [22]:

In [22]: finaldict.update(dict1)

In [23]: finaldict
Out[23]: {22: [7, 9, 8], 23: [7, 9, 8, 6, 12]}

In [24]:

Upvotes: 3

Related Questions