vem
vem

Reputation: 21

Combine two same values with same keys in a list of dictionaries

Totally a programming newbie..and need some help.

What I have is a list of dictionaries in the following format:

a_list = [
    {'ID': 'a', 'Animal': 'dog', 'color': 'white', 'tail': 'yes'},
    {'ID': 'a', 'Animal': 'cat', 'color': 'black', 'tail': 'yes'},
    {'ID': 'b', 'Animal': 'bird', 'color': 'black', 'tail': 'no'},
    {'ID': 'b', 'Animal': 'cat', 'color': 'pink', 'tail': 'yes'}
    {'ID': 'b', 'Animal': 'dog', 'color': 'yellow', 'tail': 'no'}      
   ]

What I am going for is a dict of dictionaries as follows:

a_dict = 
    {'a': {'dog': {'color': 'white', 'tail': 'yes'},
           'cat': {'color': 'black', 'tail': 'yes'}},
     'b': {'bird': {'color': 'black', 'tail': 'no'},
           'cat': {'color': 'pink', 'tail': 'no'},
           'dog': {'color': 'yellow', 'tail': 'no'}}}    

Upvotes: 0

Views: 80

Answers (5)

Sylvaus
Sylvaus

Reputation: 884

You can construct the dictionary iteratively creating inner dictionaries at every step. Here's a suggestion implementation for the general case:

def group_by_nested_keys(elements, keys):
    root = {}
    for element in elements:
        inner_dict = root
        # Create the inner dictionaries as we go through the keys
        # and remove the key from element at the same time 
        for key in keys[:-1]:
            inner_dict = inner_dict.setdefault(element.pop(key), {})

        # When all the dictionaries for the elements are created,
        # assign the element to the most inner dictionary
        inner_dict[element.pop(keys[-1])] = element

    return root



a_dict = group_by_nested_keys(a_list, ["ID", "Animal"])

Upvotes: 0

Chris Charley
Chris Charley

Reputation: 6573

Much like the other solutions offered here, this uses a default dictionary.

>>> from collections import defaultdict
>>> d = defaultdict(dict)

>>> for dict_ in a_list:
    ID = dict_.pop('ID')
    animal = dict_.pop('Animal')
    d[ID][animal] = dict_

>>> from pprint import pprint
>>> pprint(dict(d))
{'a': {'cat': {'color': 'black', 'tail': 'yes'},
       'dog': {'color': 'white', 'tail': 'yes'}},
 'b': {'bird': {'color': 'black', 'tail': 'no'},
       'cat': {'color': 'pink', 'tail': 'yes'},
       'dog': {'color': 'yellow', 'tail': 'no'}}}

Upvotes: 0

Michael Szczesny
Michael Szczesny

Reputation: 5036

An easy solution with defaultdict

from collections import defaultdict
result = defaultdict(dict)
a_list = [
    {'ID': 'a', 'Animal': 'dog', 'color': 'white', 'tail': 'yes'},
    {'ID': 'a', 'Animal': 'cat', 'color': 'black', 'tail': 'yes'},
    {'ID': 'b', 'Animal': 'bird', 'color': 'black', 'tail': 'no'},
    {'ID': 'b', 'Animal': 'cat', 'color': 'pink', 'tail': 'yes'},
    {'ID': 'b', 'Animal': 'dog', 'color': 'yellow', 'tail': 'no'}      
   ]
for item in a_list:
    result[item['ID']][item['Animal']] = {'color':item['color'], 'tail':item['tail']}

defaultdict(dict,
            {'a': {'dog': {'color': 'white', 'tail': 'yes'},
              'cat': {'color': 'black', 'tail': 'yes'}},
             'b': {'bird': {'color': 'black', 'tail': 'no'},
              'cat': {'color': 'pink', 'tail': 'yes'},
              'dog': {'color': 'yellow', 'tail': 'no'}}})

Upvotes: 0

Andrej Kesely
Andrej Kesely

Reputation: 195418

a_list = [
    {'ID': 'a', 'Animal': 'dog', 'color': 'white', 'tail': 'yes'},
    {'ID': 'a', 'Animal': 'cat', 'color': 'black', 'tail': 'yes'},
    {'ID': 'b', 'Animal': 'bird', 'color': 'black', 'tail': 'no'},
    {'ID': 'b', 'Animal': 'cat', 'color': 'pink', 'tail': 'yes'},
    {'ID': 'b', 'Animal': 'dog', 'color': 'yellow', 'tail': 'no'}      
]

a_dict = {}
for v in a_list:
    a_dict.setdefault(v['ID'], {}).setdefault(v['Animal'], {}).update(color=v['color'], tail=v['tail'])

from pprint import pprint
pprint(a_dict)

Prints:

{'a': {'cat': {'color': 'black', 'tail': 'yes'},
       'dog': {'color': 'white', 'tail': 'yes'}},
 'b': {'bird': {'color': 'black', 'tail': 'no'},
       'cat': {'color': 'pink', 'tail': 'yes'},
       'dog': {'color': 'yellow', 'tail': 'no'}}}

Upvotes: 1

Suraj
Suraj

Reputation: 2477

Created a nested dictionary and deleted all the keys not required later from it.

a_list = [
    {'ID': 'a', 'Animal': 'dog', 'color': 'white', 'tail': 'yes'},
    {'ID': 'a', 'Animal': 'cat', 'color': 'black', 'tail': 'yes'},
    {'ID': 'b', 'Animal': 'bird', 'color': 'black', 'tail': 'no'},
    {'ID': 'b', 'Animal': 'cat', 'color': 'pink', 'tail': 'yes'},
    {'ID': 'b', 'Animal': 'dog', 'color': 'yellow', 'tail': 'no'}      
   ]

a_dict = {}
for a in a_list:
    if a['ID'] in a_dict:
        a_dict[a['ID']][a['Animal']] = a
    else:
        a_dict[a['ID']] = {a['Animal']: a}

for id_ in a_dict:
    for animal in a_dict[id_]:
        del a_dict[id_][animal]['ID']
        del a_dict[id_][animal]['Animal']

Output :

>> a_dict

{'a': {'dog': {'color': 'white', 'tail': 'yes'},
  'cat': {'color': 'black', 'tail': 'yes'}},
 'b': {'bird': {'color': 'black', 'tail': 'no'},
  'cat': {'color': 'pink', 'tail': 'yes'},
  'dog': {'color': 'yellow', 'tail': 'no'}}}

Upvotes: 0

Related Questions