Skip to content Skip to sidebar Skip to footer

Combine Two Lists Of Dictionaries

[{'APPLE': ['RED']}, {'BANANA': ['YELLOW', 'GREEN']}, {'APPLE': ['GREEN']}] Using this list of dictionaries, how can i combine same keys? [{'APPLE': ['RED','GREEN']}, {'BANANA': [

Solution 1:

You may achieve the list in desired format via creating intermediate dictionary to store the mapping (even better to use collections.defaultdict) as:

from collections import defaultdict

my_list = [{"APPLE": ["RED"]}, {"BANANA": ["YELLOW", "GREEN"]}, {"APPLE": ["GREEN"]}]
temp_dict = defaultdict(list)

for item in my_list:
    for k, v in item.items():
        temp_dict[k] += v

# content of `temp_dict` is:
#     {
#          'APPLE': ['RED', 'GREEN'], 
#          'BANANA': ['YELLOW', 'GREEN']
#     }

For converting the dict to the list of desired format, you may use a list comprehension expression as:

>>> new_list = [{k: v} for k, v in temp_dict.items()]
>>> new_list
[{'APPLE': ['RED', 'GREEN']}, {'BANANA': ['YELLOW', 'GREEN']}]

Solution 2:

Without importing any modules,

a = [{"APPLE": ["RED"]}, {"BANANA": ["YELLOW", "GREEN"]}, {"APPLE": ["GREEN"]}]
temp = {}
for i in a:
    for key in i:
        if key in temp.keys():
            temp[key].extend(i[key])
        else:
            temp[key] = i[key]
# print(temp)
op = [{key:val} for key,val in temp.items()]
print(op)

Solution 3:

You can do the following. Simply iterate through each dictionary in your list and then add the key and all values, if a key has already been added then it will just extend the list with the other values.

from collections import OrderedDict

data = [{"APPLE": ["RED"]}, {"BANANA": ["YELLOW", "GREEN"]}, {"APPLE": ["GREEN"]}]

temp = OrderedDict() # use ordered dict if you want to maintain order# collapse dicts from datafor d in data:
    for key in d:
        temp.setdefault(key, []).extend(d[key])

res = [ { k : v } for k, v in temp.items() ] # split back into individual dictsprint(res)

# Output
[{'APPLE': ['RED', 'GREEN']}, {'BANANA': ['YELLOW', 'GREEN']}]

Solution 4:

If you don't need easily readable code, you may use:

data = [{"APPLE": ["RED"]}, {"BANANA": ["YELLOW", "GREEN"]}, {"APPLE": ["GREEN"]}]

keys = {key forkeylistin [item.keys() foritemin data] forkeyin keylist}
temp = {k: [color foritemin data if k in item.keys() forcolorin item[k]] forkin keys}
rslt = [{k: v} fork, v in temp.items()]
print(rslt)

>>> [{'APPLE': ['RED', 'GREEN']}, {'BANANA': ['YELLOW', 'GREEN']}]

Hint:Don't take this too serious. I was just curious about doing as much inline as possible. You could even go further and nest the comprehensions into another...

rslt = [{k: v} fork, v in {k: [color foritemin data if k in item.keys() forcolorin item[k]] forkin {key forkeylistin [item.keys() foritemin data] forkeyin keylist}}.items()]

Just for the case you want to make sure that nobody, including you, can follow this code after a while... ;)

Solution 5:

Similar to other suggested solutions but using reduce() function.

Define a helper to merge dictionaries and use it in reduce() function

defext(d1, d2):
  for k, v in d2.items():
    d1.setdefault(k, []).extend(v)
  return d1

src = [{"APPLE": ["RED"]}, {"BANANA": ["YELLOW", "GREEN"]}, {"APPLE": ["GREEN"]}]
dst = reduce(ext, src, {})
print dst
>>> {'APPLE': ['RED', 'GREEN'], 'BANANA': ['YELLOW', 'GREEN']}

Now you have a succinct data structure: a dictionary and you can do different queries on it. To get the desired output:

print [ { k : v } for k, v in dst.items() ]
[{'APPLE': ['RED', 'GREEN']}, {'BANANA': ['YELLOW', 'GREEN']}]

Out of curiosity run performance tests of listed solutions

Simplicity wins (Natarajan), obscurity fails behind (jbndir) (due to additional temporary copies).

Dictionary setdefault() function doesn't change the performance noticeably, it shortens code, so should be used instead of if else statement.

import timeit
from collections import defaultdict

deff0():
  src = [{"APPLE": ["RED"]}, {"BANANA": ["YELLOW", "GREEN"]}, {"APPLE": ["GREEN"]}]
  dst = defaultdict(list)
  for item in src:
      for k, v in item.items():
          dst[k] += v

defext(d1, d2):
  for k, v in d2.items():
    d1.setdefault(k, []).extend(v)
  return d1

deff1():
  src = [{"APPLE": ["RED"]}, {"BANANA": ["YELLOW", "GREEN"]}, {"APPLE": ["GREEN"]}]
  dst = reduce(ext, src, {})

deff2():
  src = [{"APPLE": ["RED"]}, {"BANANA": ["YELLOW", "GREEN"]}, {"APPLE": ["GREEN"]}]
  dst = {}
  for i in src:
    for key in i:
      if key in dst.keys():
        dst[key].extend(i[key])
      else:
        dst[key] = i[key]

deff3():
  src = [{"APPLE": ["RED"]}, {"BANANA": ["YELLOW", "GREEN"]}, {"APPLE": ["GREEN"]}]
  dst = {}
  for i in src:
    for key in i:
      dst.setdefault(key, []).extend(i[key])

deff4():
  src = [{"APPLE": ["RED"]}, {"BANANA": ["YELLOW", "GREEN"]}, {"APPLE": ["GREEN"]}]
  keys = {key for keylist in [item.keys() for item in src] for key in keylist}
  temp = {k: [color for item in src if k in item.keys() for color in item[k]] for k in keys}


min(timeit.repeat(lambda: f0())):  4.64622211456min(timeit.repeat(lambda: f1())):  4.51267290115min(timeit.repeat(lambda: f2())):  3.18728780746min(timeit.repeat(lambda: f3())):  3.35215997696min(timeit.repeat(lambda: f4())):  6.80625200272

Post a Comment for "Combine Two Lists Of Dictionaries"