Python: Update the dict[key] values list only with values not already in list

Viewed 941

I am trying to add/append test_dict2 to test_dict, according to the below rules:

  1. If the test_dict2 dictionary key already exists in test_dict, update test_dict[key] with only new values from test_dict2[key]
  2. If the dictionary key does not already exist in test_dict, add the key and value.

Example:

test_dict = {'s': [1, 2], 't': 2}
test_dict2 = {'s': [1, 2, 3, 'yoyoyo'], 't': 2, 'u': [3, 4]}

After my intended update, test_dict should look like this:

test_dict = {'s': [1, 2, 3, 'yoyoyo'], 't': [2], 'u': [3, 4]}

I have working code, but it seems so inefficient:

def convert_values_to_list(value):
  if isinstance(value, list) == False:
    value = [value]
  return value

for key, values in test_dict2.items():
  values = convert_values_to_list(values)
  print(key)
  print(values)
  if key not in test_dict:
    test_dict[key] = values
  else:
    test_dict[key] = convert_values_to_list(test_dict[key])
    for value in values:
      if value not in test_dict[key]:
        test_dict[key].append(value)
2 Answers

Try this.

def unpack_values(data):
    for datum in data:
        if isinstance(datum, list):
            for x in datum:
                yield x
        else:
            yield datum

all_keys=set(test_dict.keys())
all_keys.update(test_dict2.keys())

for key in all_keys:
    values=[test_dict.get(key,[]), test_dict2.get(key,[])]
    test_dict[key]=list(set(unpack_values(values)))

You could try using a library to help with this, I found deepmerge, which also supports custom strategies, so you could make this a one-liner in theory:

>>> from deepmerge import always_merger
>>> a = {'s': [1, 2], 't': 2}
>>> b = {'s': [1, 2, 3, 'yoyoyo'], 't': 2, 'u': [3, 4]}

and then

>>> always_merger.merge(a, b)  # a was modified in place
{'s': [1, 2, 1, 2, 3, 'yoyoyo'], 't': 2, 'u': [3, 4]}

>>> {k: list(set(v)) if isinstance(v, list) else [v] for k, v in a.iteritems()}
{'s': [1, 2, 3, 'yoyoyo'], 't': [2], 'u': [3, 4]}
Related