Search code examples
pythonlistdictionarykeykey-value

How to group same values of a particular key in a list of dictionary together


list = [
{'roll':101 , 'class':10},
{'roll':102 , 'class':10},
{'roll':103 , 'class':10},
{'roll':104 , 'class':11},
{'roll':105 , 'class':11},
{'roll':106 , 'class':11},
{'roll':107 , 'class':12},
{'roll':108 , 'class':12},
{'roll':109 , 'class':12} ]

Should be converted to

new_list = [
{'roll':[101,102,103] , 'class':10},
{'roll':[104,105,106] , 'class':11},
{'roll':[107,108,109] , 'class':12} ]

The initial list values will be from database . The values of roll will always be different where as class can be same . Cannot seem to figure out how to proceed.


Solution

  • This solution iterates through the list from the database (you shouldn't use list as a variable name), checks for existance in the new list and either appends to the roll list it exists, or creates the new dictionary.

    db_list = [
    {'roll':101 , 'class':10},
    {'roll':102 , 'class':10},
    {'roll':103 , 'class':10},
    {'roll':104 , 'class':11},
    {'roll':105 , 'class':11},
    {'roll':106 , 'class':11},
    {'roll':107 , 'class':12},
    {'roll':108 , 'class':12},
    {'roll':109 , 'class':12} ]
    
    new_list = []
    for item in db_list:
        for new_item in new_list:
            if new_item['class'] == item['class']:
                new_item['roll'].append(item['roll'])
                break
        else:
            new_list.append({'roll': [item['roll']], 'class': item['class']})
    
    print(new_list)
    # output 
    # [{'roll': [101, 102, 103], 'class': 10}, {'roll': [104, 105, 106], 'class': 11}, {'roll': [107, 108, 109], 'class': 12}]
    

    Alternatively, you can use an intermediate dictionary to build the new lists, which significantly improves the code readiblity,

    from collections import defaultdict
    class_roll = defaultdict(list)
    for item in db_list:
        class_roll[item['class']].append(item['roll'])
    
    new_list = [{'roll':class_roll[class_], 'class':class_} for class_ in class_roll]