【问题标题】:Merge 2 dictionaries with higher value for each key [duplicate]为每个键合并具有更高值的 2 个字典 [重复]
【发布时间】:2020-04-08 22:26:53
【问题描述】:

我有

dict1 = {a: 1, b: 2, c: 3}
dict2 = {b: 3, c: 2}

如何合并 dict1 和 dict2 以便结果 dict3 将具有 {a: 1, b: 3, c: 3} 我知道我们可以像这样 dict3 = {**a, **b} 进行合并,但是我必须在任何地方写一个条件才能解决我的问题吗?

【问题讨论】:

    标签: python


    【解决方案1】:

    给你:

    dict1 = {"a": 1, "b": 2, "c": 3}
    dict2 = {"b": 3, "c": 2}
    
    result = {}
    for k in dict1.keys() | dict2.keys():
        result[k] = max(dict1.get(k, float('-inf')), dict2.get(k,float('-inf')))
    
    print(result)
    

    我正在使用默认值:dict1.get(k, DEFAULT) 并使用按位 OR 运算符 | 连接两个键集。

    请注意,float('-inf') 的默认值表示结果为

    dict1 = {"a": -1, "b": 2, "c": 3}
    dict2 = {"b": -5, "c": 2}```
    

    变成{'a': -1, 'b': 2, 'c': 3}

    而默认的0 你会得到 {'b': 2, 'c': 3, 'a': 0}

    这两种方式都可以被视为同样有效的响应。

    【讨论】:

    • 您可以通过将float('-inf') 移出循环来加快速度。 (回复your comment
    • 我的测试不公平。我已经使用默认 0 进行了测试,我刚刚意识到。因此,如果时间在这里真的是一个问题,那么您的解决方案将获胜。然而,从可读性的角度来看,我更喜欢我的“for-max”解决方案,而不是更快的“for-for-if-larger”解决方案。
    【解决方案2】:

    您可以将 dict 项合并到一个元组序列中,对它们进行排序,然后使用 dict 构造函数从排序后的序列中创建一个新的 dict,以便具有相同键但具有更高值的项将覆盖那些具有较低的值:

    dict(sorted((*dict1.items(), *dict2.items())))
    

    【讨论】:

    • 我真的很喜欢这个解决方案,老实说我没有看到它。有趣的是,它比其他两种解决方案慢一点。但我不明白为什么。我为这个测量了 12ms,我的测量为 3.8(for-max-solution),for-for-if-larger-solution 测量了 2.6。
    • @LydiavanDyke 很高兴你喜欢它。不确定您如何测量它,但在我的测试中,它是给定输入的 3 个答案中最快的。查看演示:repl.it/@blhsing/ElectronicElasticExams
    • 我使用了更大的数字。但在 repl.it n 上大于 100 不会终止:) repl.it/repls/StaleFluffyNotifications
    • 我明白了。实际上,排序的问题在于它的平均时间复杂度为 O(n log n),而其他跟踪循环中每个键的最大值的解决方案的成本为 O(n )。因此,对于非常大的听写,应该坚持使用线性解决方案。顺便说一句,您的演示代码将完成,但需要很长时间。尝试降低timeitnumber 参数,因为您使用的是更大的nrepl.it/@blhsing/StaleFluffyNotifications
    • 啊,我不习惯摆弄timeit的数字。我通常只是在我的 ipython 控制台中输入“timeit”。无论如何,很高兴与您和@wjandrea 一起编码。就我所见,我们得到了一个快速的解决方案,一个pythonic的解决方案和一个可读的解决方案:)
    【解决方案3】:

    您可以简单地遍历它们并比较值,然后使用dict.setdefault(key, 0) 绕过未设置的值。

    dict1 = {'a': 1, 'b': 2, 'c': 3}
    dict2 = {'b': 3, 'c': 2}
    
    dict3 = {}
    for d in dict1, dict2:
        for k, v in d.items():
            if v > dict3.setdefault(k, 0):
                dict3[k] = v
    print(dict3)  # -> {'a': 1, 'b': 3, 'c': 3}
    

    defaultdict(int) 也可以,但我想避免导入。

    【讨论】:

    • 也许float('-inf') 会是一个更好的默认值,idk
    • 这是一个非常好的观点!你刚刚发现了一个错误。至少对于我的代码而言。
    • 哦,谢谢。我不知道 dict.setdefault 的事情
    • 嗯。或者你……我不确定。我认为,它可以去任何一种方式。
    • @Lydia 这就是我说“idk”的原因;)实际上,虽然我认为最好先检查成员资格然后比较而不是使用默认值,至少在我的代码中。
    猜你喜欢
    • 2011-10-17
    • 2020-04-04
    • 1970-01-01
    • 2022-01-02
    • 1970-01-01
    • 1970-01-01
    • 2021-06-22
    • 2013-11-20
    • 2015-02-05
    相关资源
    最近更新 更多