Home > Software engineering >  Group dicts from a list by the values of a certain key
Group dicts from a list by the values of a certain key

Time:01-19

I have a list with dicts like this:

d = [ {'key1': 1, 'key2': 10, 'key3': 0.75, 'key4':5},
 {'key1': 2, 'key2': 20, 'key3': 0.6, 'key4':4},
 {'key1': 3, 'key2': 10, 'key3': 0.8, 'key4':8
 {'key1': 4, 'key2': 30, 'key3': 0.86, 'key4':2},
 {'key1': 5, 'key2': 10, 'key3': 0.9, 'key4':7},
 {'key1': 6, 'key2': 20, 'key3': 0.73, 'key4':3},
]

and I want to group the dicts that have the same value in the key2. Like this:

d10= [{'key1': 1, 'key2': 10, 'key3': 0.75, 'key4':5},
 {'key1': 3, 'key2': 10, 'key3': 0.8, 'key4':8},
 {'key1': 5, 'key2': 10, 'key3': 0.9, 'key4':7} ]

d20= [ {'key1': 2, 'key2': 20, 'key3': 0.6, 'key4':4},
 {'key1': 6, 'key2': 20, 'key3': 0.73, 'key4':3} ]

d30=[ {'key1': 4, 'key2': 30, 'key3': 0.86, 'key4':2} ]

Can you help me?

CodePudding user response:

Here is one approach using defaultdict:

from collections import defaultdict                                                            

res = defaultdict(list)                                                                        

for obj in d: 
     key = obj['key2'] 
     res[key].append(obj)                                                                                               

Output:

defaultdict(list,
            {10: [{'key1': 1, 'key2': 10, 'key3': 0.75, 'key4': 5},
              {'key1': 3, 'key2': 10, 'key3': 0.8, 'key4': 8},
              {'key1': 5, 'key2': 10, 'key3': 0.9, 'key4': 7}],
             20: [{'key1': 2, 'key2': 20, 'key3': 0.6, 'key4': 4},
              {'key1': 6, 'key2': 20, 'key3': 0.73, 'key4': 3}],
             30: [{'key1': 4, 'key2': 30, 'key3': 0.86, 'key4': 2}]})

CodePudding user response:

Using sorted and itertools.groupby. I also use operator.itemgetter as a helper method in place of using a lambda:

from itertools import groupby
from operator import itemgetter

get_key2 = itemgetter('key2')
result = {k: list(g) for k, g in groupby(sorted(d, key=get_key2), get_key2)}

CodePudding user response:

There are already some good answers, but I would also like to present my approach in case it helps:

import itertools
d = [ {'key1': 1, 'key2': 10, 'key3': 0.75, 'key4':5},
 {'key1': 2, 'key2': 20, 'key3': 0.6, 'key4':4},
 {'key1': 3, 'key2': 10, 'key3': 0.8, 'key4':8},
 {'key1': 4, 'key2': 30, 'key3': 0.86, 'key4':2},
 {'key1': 5, 'key2': 10, 'key3': 0.9, 'key4':7},
 {'key1': 6, 'key2': 20, 'key3': 0.73, 'key4':3},
]

result = {}
for _, e in itertools.groupby(d, lambda s: s["key2"]):
    x = [g for g in e]
    print(_, x)
    if 'd{}'.format(_) not in result:
        result['d{}'.format(_)] = x
    else:
        result['d{}'.format(_)]  = x


print(result)

Output:

{'d10': [{'key1': 1, 'key2': 10, 'key3': 0.75, 'key4': 5}, {'key1': 3, 'key2': 10, 'key3': 0.8, 'key4': 8}, {'key1': 5, 'key2': 10, 'key3': 0.9, 'key4': 7}], 
'd20': [{'key1': 2, 'key2': 20, 'key3': 0.6, 'key4': 4}, {'key1': 6, 'key2': 20, 'key3': 0.73, 'key4': 3}], 
'd30': [{'key1': 4, 'key2': 30, 'key3': 0.86, 'key4': 2}]}

CodePudding user response:

an another approach is:

def groupby(dictionaries, bykey):
    keys = {dictionary[bykey] for dictionary in dictionaries}
    
    groups = []
    for key in keys:
        groups.append([dictionary for dictionary in dictionaries
                       if dictionary[bykey] == key])

    return groups

output:

>>> groupby(d, 'key2')
>>> [
    [
        {'key1': 1, 'key2': 10, 'key3': 0.75, 'key4': 5},
        {'key1': 3, 'key2': 10, 'key3': 0.8, 'key4': 8},
        {'key1': 5, 'key2': 10, 'key3': 0.9, 'key4': 7}
    ],
    [
        {'key1': 2, 'key2': 20, 'key3': 0.6, 'key4': 4},
        {'key1': 6, 'key2': 20, 'key3': 0.73, 'key4': 3}
    ],
    [
        {'key1': 4, 'key2': 30, 'key3': 0.86, 'key4': 2}
    ]
]
  •  Tags:  
  • Related