Searching for a more elegant (less code) way to compare multiple dicts

大城市里の小女人 提交于 2019-12-11 07:28:56

问题


a while ago i asked a question about comparing 2 dicts to eachother, in order to detect same key's and keep the highest value of duplicates. this community came with the a soltion which allowed me to compare 2 dicts to eachother and store the highest value of it in a new dict, which i can then compare to another dict if neccesary.

but as the number of dicts are getting higher, the code itself keeps getting larger.

for key in dict1:
    if key not in dict2 or dict1[key] > dict2[key]:
        dict2[key] = dict1[key]
dict2a = {**dict1, **dict2}

for key in dict2a:
    if key not in dict3 or dict2a[key] > dict3[key]:
         dict3[key] = dict2a[key]
dict3a = {**dict2a, **dict3}

for key in dict3a:
    if key not in dict4 or dict3a[key] > dict4[key]:
        dict4[key] = dict3a[key]
dict4a = {**dict3a, **dict4}

Im trying to come up with a solution that will iterate over all these dicts. This question also hangs together with another question, but to keep solutions seperated, i ask this question in another help-question (how to open up multiple json txt files without getting errors and stops). Trying to get shorter way of opening multiple txt files

In short, atm im creating a dict for each played contest, with playernames as key's and their scores a values. This dict comparison is needed to filter playernames who attended to more then 1 contest, and to keep only their highest score. But perhaps another solution to this is to store all those different dicts in 1 big nested dict. That is at least the hint my teacher gave me. But i cannot find a way to compare nested dicts to eachother, and thus atm im bound to all these seperated dicts.

If any info is unclear please let me know so i can try to clearify it more.

thnx in advance

update: an example of what is reached after a comparison:

dict1 = {"name1": 100, "name2": 20, "name4": 111}
dict2 = {"name4": 112, "name5": 23}

compared_dict = {"name1": 100, "name2": 20, "name4": 112, "name5": 23}

回答1:


So the two rules are:

  1. Filter out duplicates
  2. Include the score of the newest dictionary if it is greater than the old one

You are copying a lot of code... one of the first rules of coding best practices is DRY (don't repeat yourself!)

Let's define a method to merge our old and new dictionaries

def merge_dictionaries(old, new):
    changes = {}
    # keep the old one, don't edit the new one
    copy = old.copy()
    for player in new.keys():
        new_score = new[player]
        try:
            old_score = old[player]
        except KeyError:
            # if player doesn't exist in the old set, add them to the changes
            changes[player] = new_score
            continue
        if new_score > old_score:
            changes[player] = new_score
    copy.update(changes)
    return copy

The next step would be to iterate over a list of these dictionaries containing playernames and scores to total to a final result using the method above.

One solution may look like this:

def final_result(list_of_games):
    final = {}
    for results in list_of_games:
        final = merge_dictionaries(final, results)
    return final

A working example:

def merge_dictionaries(old, new):
    changes = {}
    # keep the old one, don't edit the new one
    copy = old.copy()
    for player in new.keys():
        new_score = new[player]
        try:
            old_score = old[player]
        except KeyError:
            # if player doesn't exist in the old set, add them to the changes
            changes[player] = new_score
            continue
        if new_score > old_score:
            changes[player] = new_score
    copy.update(changes)
    return copy

def final_result(list_of_games):
    final = {}
    for results in list_of_games:
        final = merge_dictionaries(final, results)
    return final

games = [
    {'kevin': 1, 'jack': 5},
    {'kevin': 2, 'blueberry': 1, 'jack': 3},
    {'kevin': 1, 'blueberry': 5, 'jack': 10}
    ]

print(final_result(games))

Which outputs

{'kevin': 2, 'jack': 10, 'blueberry': 5}



回答2:


The processing you've described doesn't sound like comparing dictionaries is required—it seems like you want to merge them together (and retaining only the highest score obtained by each player).

The combine_dicts() function below will accept any number of input dictionaries (collectively named args because of the * prefix.)

def combine_dicts(*args):
    combined = {}
    for arg in args:
        for player, score in arg.items():
            combined[player] = max(combined.get(player, 0), score)
    return combined

dict1 = {"name1": 100, "name2": 20, "name4": 111}
dict2 = {"name4": 112, "name5": 23}

result  = combine_dicts(dict1, dict2)
print(result)

Output:

{'name1': 100, 'name2': 20, 'name4': 112, 'name5': 23}


来源:https://stackoverflow.com/questions/47877373/searching-for-a-more-elegant-less-code-way-to-compare-multiple-dicts

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!