Legion
Legion

Reputation: 474

How to update dictionary and its list contents?

I've created two dictionaries that I wish to combine like this:

dict1 = {'temp1':[1,2,3,4]}
dict2 = {'temp1': [3,4,5],'temp2':[15,16,17]}
dict1.update(dict2)

I was hoping to get this:

dict1 = {'temp1': [1, 2, 3, 4, 5], 'temp2': [15, 16, 17]}

But instead I get this:

dict1 = {'temp1': [3, 4, 5], 'temp2': [15, 16, 17]}

How do I update and filter out duplicates in the lists in the dictionary?

Upvotes: 1

Views: 215

Answers (5)

Anton vBR
Anton vBR

Reputation: 18906

If they can't repeat why not use sets from the start?

dict1 = {'temp1': {1,2,3,4}}
dict2 = {'temp1': {3,4,5},'temp2':{15,16,17}}

for k,v in dict2.items():
    dict1[k] = v.union(dict1.get(k,{}))

print(dict1)

Returns:

{'temp1': {1, 2, 3, 4, 5}, 'temp2': {15, 16, 17}}

Upvotes: 0

niraj
niraj

Reputation: 18208

May not be the most efficient way but one way may be as following:

  • Iterate over key for one of the dictionary and check if same key exist in other dictionary.
  • If it exist then, update values that do not exist (you can use set for this purpose or loop values).
  • If it does not exist then, add key and copy values to the dictionary.

dict1 = {'temp1':[1,2,3,4]}
dict2 = {'temp1': [3,4,5],'temp2':[15,16,17]}


for key in dict2: # check over keys in dict2
    if key in dict1: # if key also exist in dict1 then update values
        for v in dict2[key]:
            if v not in dict1[key]:  # update values only if does not exist
                dict1[key].append(v)
    else: # if key does not exist copy the values from dict2 for the key
        dict1[key] = dict2[key][:]

# dict1 is {'temp2': [15, 16, 17], 'temp1': [1, 2, 3, 4, 5]}

Upvotes: 0

Thierry Lathuille
Thierry Lathuille

Reputation: 24232

You could create a subclass of dict that updates lists the way you want:

from collections import UserDict

class ListDict(UserDict):
    def __init__(self, data_as_dict):
        self.data = data_as_dict

    def update(self, other):
        for key, sublist in other.items():
            self.data[key] = list(set(self.data.get(key, [])) | set(sublist))

dict1 = {'temp1':[1,2,3]}
dict2 = {'temp1': [3,4,5],'temp2':[15,16,17]}

d = ListDict(dict1)
d.update(dict2)
print(d)

# {'temp1': [1, 2, 3, 4, 5], 'temp2': [16, 17, 15]}

Upvotes: 1

Sushant
Sushant

Reputation: 3669

Since your dict contains list, we could do something like this-

dict1 = {'temp1':[1,2,3]}
dict2 = {'temp1': [3,4,5],'temp2':[15,16,17]}
for k, v in dict1.iteritems():
    try:
        dict2[k] = list(set(dict2[k]+v))
    except KeyError:
        pass

Obviously this method is hacky but solves the problem. You should probably see Jean's answer as this answer is how something can be done but there always are better ways to doing it

Upvotes: 0

Jean-François Fabre
Jean-François Fabre

Reputation: 140168

dict.update replaces the values under existing keys, which explains the result you're getting (your values are lists of integers, but the update method isn't aware of that, and wouldn't know how to merge the data anyway)

Here, you've created a specialized dictionary, with values being list of integers.

What you want is a custom merge function.

I would rebuild a third dict using dict comprehension on the union of the keys, and merging the lists as a set (for unicity) then turn back to list:

dict1 = {'temp1':[1,2,3]}
dict2 = {'temp1': [3,4,5],'temp2':[15,16,17]}

dict3 = {k:list(set(dict1.get(k,[])+dict2.get(k,[]))) for k in set(dict2) | set(dict1)}

print(dict3)

result:

{'temp2': [16, 17, 15], 'temp1': [1, 2, 3, 4, 5]}

The magic of dict1.get(k,[]) is that if the key isn't present, it returns an empty list so + works and the expression isn't too complex.

the order of the elements isn't guaranteed because of the use of a set at some point. You could use sorted(set ...) instead of simple conversion to list to guarantee that the integer values are sorted.

Upvotes: 2

Related Questions