'Combine a list of multiple dictionaries into on single dict based on condition

I want to merge some of the dictionaries, condition is whenever they have the same value in age and experience then I need to merge all the dict and keep the dict that doesn't below to this condition.

I have the following list of dictionaries:

lst = [
        {
            "Game": "Lego",
            "players": [         
            {   "training":"2",
                "Age": "28",
                "Experience": "no",
                "Score": [
                    {
                        "Alicia": 87
                    }
                ]
            },
                {
                    "Age": "20",
                    "Experience": "yes",
                    "Score": [
                        {
                            "Alex": 230
                        }
                    ]
                },
                {
                    "Age": "20",
                    "Experience": "yes",
                    "Score": [
                        {
                            "juana": 275
                        }
                    ]
                }
            ],
            "season": "summer"

        }
    ]

The output should look like this:

[
        {
            "Game": "Lego",
            "players": [
            {   "training":"2",
                "Age": "28",
                "Experience": "no",
                "Score": [
                    {
                        "Alicia": 87
                    }
                ]
            },         
                {
                    "Age": "20",
                    "Experience": "yes",
                    "Score": [
                        {
                            "Alex": 230
                        },
                        {
                            "juana": 275
                        }
                    ]
                }
            ],
            "season": "summer"
        }
    ]

I'm blocked in checking if the age/experience are equal after this step.

for d in lst:
        for i, sd in enumerate(d['players']):
            d['players'][i] = {k: v for k, v in d['players'][i].items()}

Note:

  • i have multiple dict not only 2
  • There is some keys existing in some dict e.g training


Solution 1:[1]

Note that this code is very messy and could be done much better, but I think it does the job:

    result_lst = []

for game_dict in lst:

    result_dict = {}
    result_dict['Game'] = game_dict['Game']
    result_dict['players'] = []
    result_dict['season'] = game_dict['season']

    for player_dict1 in game_dict['players']:

        starting_idx = game_dict['players'].index(player_dict1) + 1

        for player_dict2 in game_dict['players'][starting_idx:]:

            if player_dict1['Age'] == player_dict2['Age'] and player_dict1['Experience'] == player_dict2['Experience']:

                age = player_dict1['Age']
                experience = player_dict1['Experience']

                for result_player in result_dict['players']:

                    if age == result_player['Age']:

                        if player_dict1['Score'][0] not in result_player['Score']:
                            result_player['Score'].append(player_dict1['Score'][0])

                        if player_dict2['Score'][0] not in result_player['Score']:
                            result_player['Score'].append(player_dict2['Score'][0])

                        break
                
                else:

                    players_dict = {'Age': age,
                                    'Experience': experience,
                                    'Score': [player_dict1['Score'][0],
                                            player_dict2['Score'][0],
                                    ]
                    }

                    result_dict['players'].append(players_dict)
    
    in_result_dict = True

    for player_dict in game_dict['players']:
        
        for result_players in result_dict['players']:
            for result_player in result_players['Score']:
                
                if player_dict['Score'][0] == result_player:
                    in_result_dict = False
                    break

        if in_result_dict:
            result_dict['players'].append(player_dict)

    result_lst.append(result_dict)


print(result_lst)

Also note that this way of storing information is too redundant and makes it hard to access the data and iterate over it, please consider refactoring it.

Anyway, the output is:

[{'Game': 'Lego', 
'players': [{'Age': '20', 
            'Experience': 'yes', 
            'Score': [{'Alex': 230}, {'juana': 275}]}, 
            
            {'Age': '28', 
                'Experience': 'yes', 
                'Score': [{'Alicia': 987}]}], 
'season': 'summer'}]

Solution 2:[2]

You could try this. Here I try to

1 convert the players list to dataframe 2 Then do a group by on the df to match for Age and experience and get Score. 3 Convert this dataframe back to dict, which is later updated to the original lst

import pandas as pd
lst = [] #Replace this with your list.
players = lst[0]['players']
print('Players before update\n', players)

df = pd.DataFrame.from_dict(players)
df_new = df.groupby(['Age','Experience'])['Score'].sum().reset_index()
players = df_new.to_dict('records')    
print('Players after update \n', players)    

print('lst before update\n', lst)
lst[0]['players'] = players
print('lst after update \n', lst)

Output:

Players before update
 [{'Age': '20', 'Experience': 'yes', 'Score': [{'Alex': 230}]}, {'Age': '20', 'Experience': 'yes', 'Score': [{'juana': 275}]}]
Players after update 
 [{'Age': '20', 'Experience': 'yes', 'Score': [{'Alex': 230}, {'juana': 275}]}]
lst before update
 [{'Game': 'Lego', 'players': [{'Age': '20', 'Experience': 'yes', 'Score': [{'Alex': 230}]}, {'Age': '20', 'Experience': 'yes', 'Score': [{'juana': 275}]}], 'season': 'summer'}]
lst after update 
 [{'Game': 'Lego', 'players': [{'Age': '20', 'Experience': 'yes', 'Score': [{'Alex': 230}, {'juana': 275}]}], 'season': 'summer'}]

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2