寻找一种更优雅(更少代码)的方法来比较多个dict

2024-04-20 10:25:44 发布

您现在位置:Python中文网/ 问答频道 /正文

前段时间我问了一个关于比较两个dict的问题,目的是检测同一个key并保持最大的重复值。 这个社区提供了一个解决方案,允许我将两个dict相互比较,并将其中的最高值存储在一个新dict中,如果需要的话,我可以将其和另一个dict进行比较。你知道吗

但是随着dict的数量越来越多,代码本身也越来越大。你知道吗

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}

我试图想出一个解决方案,将迭代所有这些格言。 这个问题还与另一个问题联系在一起,但是为了保持解决方案的独立性,我在另一个帮助问题(如何打开多个json-txt文件而不出现错误和停止)中提出了这个问题。 Trying to get shorter way of opening multiple txt files

简言之,我为每一场比赛创建了一个dict,其中playernames是关键,他们的分数是一个值。 这种比较是过滤参加过一次以上比赛的玩家所需要的,并且只保留他们的最高分数。 但也许另一种解决方法是将所有不同的dict存储在一个大的嵌套dict中,这至少是老师给我的提示。但是我找不到一种方法来比较嵌套的dict,因此我绑定到所有这些独立的dict。你知道吗

如果任何信息不清楚,请让我知道,这样我可以尝试澄清它更多。你知道吗

提前通知

更新: 比较后得出的结果示例:

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

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

Tags: orkeyinforifnot解决方案dict
2条回答

你所描述的处理听起来不像是需要比较字典,似乎你想把它们合并在一起(并且只保留每个玩家获得的最高分数)。你知道吗

下面的combine_dicts()函数将接受任意数量的输入字典(由于*前缀,因此统称为args

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)

输出:

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

所以这两条规则是:

  1. 过滤掉重复项
  2. 如果最新词典的分数大于旧词典的分数,则包括该分数

你在复制很多代码。。。编码最佳实践的首要规则之一是枯燥(不要重复!)你知道吗

让我们定义一个合并新旧词典的方法

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

下一步是使用上面的方法迭代这些字典的列表,其中包含playername和scores to total,最终得到一个结果。你知道吗

一种解决方案可能如下所示:

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

一个有效的例子:

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))

哪些输出

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

相关问题 更多 >