Shan
Shan

Reputation: 19273

combining two dictionaries and still have the references to original objects in python

I have two dictionaries and I want to combine the contents of both in order to process them in a combined way. I do the following

a = {'one': 'fileone', 'two': 'filetow'}
b = {'three': 'filethree', 'four': 'filefour'}
clist = a.values() + b.values()

If I change anything in the clist, the change is not reflected in list a or b.

One thing I understand is that the string is immutable type.

I would still want to be able to refer to the old strings and changes to them must reflect in the original string.

Thanks

Upvotes: 2

Views: 43

Answers (4)

redoc
redoc

Reputation: 2469

Seeing none of the mentioned answer addresses this easier method:
Use chainmap, which is meant for this,but in this approach you change clist with keys. and the changes in values are reflected in a or b as needed.

from collections import ChainMap

a = {'one': 'fileone', 'two': 'filetwo'}
b = {'three': 'filethree', 'four': 'filefour'}

combined = ChainMap(a, b) #Note this is not a dict object but behaves similarly

# Modify the combined dictionary
combined['one'] = 'newfileone'

print(a)  # {'one': 'newfileone', 'two': 'filetwo'}

Upvotes: 0

hspandher
hspandher

Reputation: 16753

You can update one of the dicts with the values of the other one.

a.update(b)

However, the further changes in a still won't be reflected in b. To accomplish that, I suppose you are better off creating your own data structure.

# Something on these lines

class MyDict(dict):
    def __init__(self, dict1, dict2):
        super(MyDict, self).__init__(dict1, dict2)
        self.dict1 = dict1
        self.dict2 = dict2

    def __getitem__(self, key):
        if key in self.dict1:
            return self.dict1[key]
        if key in self.dict2:
            return self.dict2[key]
        return super(MyDict, self).__getitem__(key)

    def __setitem__(self, key, value):
        if key in self.dict1:
            return self.dict1[key] = value
        elif key in self.dict2:
            return self.dict2[key] = value

        return super(MyDict, self).__setitem__(key, value)

Now if you want to mutate strings, that's not possible. Strings are immutable in Python.

Upvotes: 0

tboz203
tboz203

Reputation: 484

If you wrap your strings (which are indeed immutable) with something that is mutable, you can get the effect I think you're looking for

a = {'one': ['fileone'], 'two': ['filetwo']}
b = {'three': ['filethree'], 'four': ['filefour']}

clist = a.values() + b.values()

print(clist)

a['one'][0] = 'different_file'

print(clist)

The output looks like this:

[['filetwo'], ['fileone'], ['filefour'], ['filethree']]
[['filetwo'], ['different_file'], ['filefour'], ['filethree']]

Upvotes: 1

John Zwinck
John Zwinck

Reputation: 249532

As you have already pointed out, strings are immutable. Your clist is a Python list, which means it is a mutable collection of strings, held by reference. You can add to the list, or remove from it, but clearly this has no impact on a and b. You can also replace strings in the list, but again this has no impact on a and b. You cannot "modify" a string in the list, because strings are immutable.

So, you have painted yourself into a corner. You'll need to rethink some part of your code. For example, you could make a tiny class which holds a string, and then if you store instances of that class instead of actual strings, you will be able to "modify" them by swapping out the references to strings inside. An extra layer of indirection.

Upvotes: 0

Related Questions