简体   繁体   中英

Combine values of same keys in a list of dicts

I have a list of dictionaries in the following format:

foo = [
    {'a': 'x', 'b': 'y', 'c': 'z'},
    {'a': 'j', 'c': 'z'}
]

I want to group this list of dictionaries into a single dictionary, like:

bar = {
    'a': ['x', 'j'],
    'b': ['y', None],
    'c': ['z', 'z']
}

What I've currently done is, looping through all the dicts in foo and create a list of keys and then looping again over the same to create bar . I wonder whether there is a simpler way to accomplish this. Can anyone help?

bar = {
    k: [d.get(k) for d in foo]
    for k in set().union(*foo)
}

Things to google:

  • python list comprehension
  • python dict comprehension
  • python star
  • python dict get
  • python set union

I am just going to complement Alex Hall solution here, so that it does not return a lot of "None" values:

def merge_dictionary_list(dict_list):
  return {
    k: [d.get(k) for d in dict_list if k in d] # explanation A
    for k in set().union(*dict_list) # explanation B
  }

Explanation:

  • The whole thing inside {} is a dictionary comprehension
  • Explanation A : Go through all elements in dictionary list and get values for current key k if the current dictionary ( d ) being evaluated actually has that key.

OBS: Without the if k in d expression there could be a bunch of None values appended to the arrays in case the list of dictionaries contains different types of keys.

  • Explanation B : gets all keys from list of dictionary and unite them distinctly by using set().union . After all we can only have distinct elements in set data structure.

If you want to do it the traditional way, just go with:

def merge_list_of_dictionaries(dict_list):
  new_dict = {}
  for d in dict_list:
    for d_key in d:
      if d_key not in new_dict:
        new_dict[d_key] = []
      new_dict[d_key].append(d[d_key])
  return new_dict

I think the first solution looks more elegant, but the second one is more legible/readable.

Kind Regards :)

I would do this in two steps:

  1. Collect all keys into a single iterable:

     >>> import operator >>> from functools import reduce >>> all_keys = reduce(operator.or_, (d.keys() for d in foo)) >>> all_keys {'a', 'b', 'c'}
  2. Use a dict comprehension to create the desired result:

     >>> bar = {key: [d.get(key) for d in foo] for key in all_keys} >>> bar {'a': ['x', 'j'], 'b': ['y', None], 'c': ['z', 'z']}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM