Home > database >  How to compare and remove values from nested dictionary
How to compare and remove values from nested dictionary

Time:08-02

I have nested dictionary with user input data:

{
    name: {key_to_compare: value, key_to_compare: value},
    name: {key_to_compare: value, key_to_compare: value},
    name :{key_to_compare: value, key_to_compare: value},
    ...

Number of name-key as well nested {key_to_compare: value} might vary. Then as input a get two name_key

The task is to compare the values of the same key_to_compare under different name-key and the key_to_compare with lower value to be removed. At the end the dictionary should keep the same format. This is what I have tried:

first_player, second_player = split_line
player_to_remove[first_player] = []
player_to_remove[second_player] = []
if first_player in players_data.keys() and second_player in players_data.keys():
    for fp_keys, fp_value in players_data[first_player].items():
        for sp_keys, sp_value in players_data[second_player].items():
            if fp_keys == sp_keys:
                if fp_value > sp_value:
                    player_to_remove[second_player].append(sp_keys)
                    break
                elif fp_value < sp_value:
                    player_to_remove[first_player].append(fp_keys)
                    break
                elif fp_value == sp_value:
                    break
    if player_to_remove:
        for key, value in player_to_remove.items():
            for skill, points in players_data[key].items():
                if skill in value:
                    players_data[key].pop(skill)

This is part of the a the code that handle it. I try to loop the name_key and compare the key_to_compare values. The problems is that I can't modify the dictionary during the loops. I tried to collect the key_to_compare in a separate dict with name as a key and a list of key_to_compare as values and then comparing to dictionaries to remove the matching key_to_compare for corresponding key_names. I can't figure it out how to do it and may be there is some different approach in the first place. This example of the dictionary: {'Peter': {'Adc': 400}, 'Bush': {'Tank': 150}, 'Frank': {'Mid': 200, 'Support': 250, 'Tank': 250}}

CodePudding user response:

I will suppose that your dictionnary is in the form that I'm writing here. In that case, the following code should work

dict = { 'alice' : {'key1' : 1, 'key2' : 2},'bob' : {'key2' : 0.1, 'key3' : 5}, 'carol' : {'key4' : 1}}

#Get the list of all keys, using set.union
listOfKeys = set.union(*[ set(dict[d].keys()) for d in dict ])

print(listOfKeys)
#{'key1', 'key2', 'key3', 'key4'}

#Get, for each key, a dict of every name who has the key
for k in listOfKeys : 
    namesWithKey = { name : dict[name][k] for name in dict for nameKey in dict[name] if k in nameKey}
    print(k,namesWithKey)
# key3 {'bob': 'key3'}
# key1 {'alice': 'key1'}
# key2 {'alice': 'key2', 'bob': 'key2'}
# key4 {'carol': 'key4'}
    
    #Remove the smallest one
    if len(namesWithKey) > 1 : 
        minName =  min(namesWithKey,key=namesWithKey.get)
        del dict[minName][k]

print(dict)
# {'alice': {'key1': 1, 'key2': 2}, 'bob': {'key3': 5}, 'carol': {'key4': 1}}

Here, we have an arbitrary number of keys and names, and only the intersection get removed, see key 2 that both Alice and Bob have.

Is that the question ?

CodePudding user response:

EDIT:

dct = {
    "Peter": {"Adc": 400},
    "Bush": {"Tank": 150},
    "Frank": {"Mid": 200, "Support": 250, "Tank": 250},
}


def compare(dct, key1, key2):
    item1 = dct.pop(key1) if key1 in dct else {}
    item2 = dct.pop(key2) if key2 in dct else {}

    for k in item1.keys() & item2.keys():
        if item1[k] > item2[k]:
            item2.pop(k)
        elif item1[k] < item2[k]:
            item1.pop(k)

    if item1:
        dct[key1] = item1

    if item2:
        dct[key2] = item2


compare(dct, "Bush", "Frank")
print(dct)

Prints:

{"Peter": {"Adc": 400}, "Frank": {"Mid": 200, "Support": 250, "Tank": 250}}
  • Related