【问题标题】:Compare two dict values keeping lowest value比较两个保持最小值的字典值
【发布时间】:2020-04-25 13:16:40
【问题描述】:

我正在尝试编写一个函数,它接收两个字典并返回一个合并的字典,其中包含两个字典中的所有键,如果两个字典中都存在任何键,则比较 prices 以保持最小值。

x = "{'45': 450, '43': 500, '44.5': 420, '39': 415, '47': 320, '46': 520, '44': 400, '47.5': 480, '40.5': 407, '42.5': 407, '42': 401, '38': 401, '45.5': 435, '37.5': 415, '41': 506, '38.5': 787, '36': 399, '36.5': 410, '48.5': 380, '40': 406, '48': 287, '49.5': 567, '50.5': 850, '51.5': 399, '49': 386}"
y = "{'36': 345.0, '36.5': 360.0, '37.5': 355.0, '38': 375.0, '38.5': 375.0, '39': 370.0, '40': 380.0, '40.5': 395.0, '41': 345.0, '42': 300.0, '42.5': 230.0, '43': 220.0, '44': 220.0, '44.5': 220.0, '45': 220.0, '45.5': 290.0, '46': 225.0, '47': 300.0, '47.5': 265.0, '48': 425.0, '48.5': 275.0, '49': 2000.0, '49.5': 1350.0, '51.5': 2000.0}"

我写了这个函数来做到这一点,但我相信它可以用更pythonic的方式来写

import ast
def compare_prices(dict1,dict2):
    temp1 = ast.literal_eval(dict1)
    temp2 = ast.literal_eval(dict2)
    for k,v in temp1.items():
        if k in temp2.keys():
            price = temp2[k] if temp2[k] else False
            if price:
                if v> price:
                    temp1[k] = price
                else:
                    temp1[k] = v
            else:
                temp1[k] = v
        else:
            temp1[k] = v
    for k,v in temp2.items():
        if k not in temp1.keys():
            try:
                temp1[k] = v if v else ''
            except TypeError:
                temp1[k] = v
    return dict(sorted(temp1.items()))

【问题讨论】:

  • 你想要的输出是什么?
  • 这能回答你的问题吗? keep highest value of duplicate keys in dicts
  • @DirtyBit,猜猜标题中提到了预期的输出。
  • @dvlper 基于给定样本数据的显式输出样本比猜测要好

标签: python dictionary


【解决方案1】:

我相信这会满足您的要求。它更简单,因为它使用了一组键,因此 set1.intersection(set2) 包含两组中的所有键,因此它可以使用它来进行比较,而 set2-set1 只包含 set2 独有的那些,所以它们可以简单地移至set1

def compare_prices(dict1,dict2):
    temp1 = ast.literal_eval(dict1)
    temp2 = ast.literal_eval(dict2)
    set1 = set(temp1.keys())
    set2 = set(temp2.keys())
    for k in set1.intersection(set2):
        if temp1[k] > temp2[k]:
            temp1[k] = temp2[k]
    for k in set2 - set1:
        temp1[k] = temp2[k]
    return dict(sorted(temp1.items()))

输出是:

print(compare_prices(x, y))
{'36': 345.0, '36.5': 360.0, '37.5': 355.0, '38': 375.0, '38.5': 375.0, '39': 370.0, '40': 380.0, '40.5': 395.0, '41': 345.0, '42': 300.0, '42.5': 230.0, '43': 220.0, '44': 220.0, '44.5': 220.0, '45': 220.0, '45.5': 290.0, '46': 225.0, '47': 300.0, '47.5': 265.0, '48': 287, '48.5': 275.0, '49': 386, '49.5': 567, '50.5': 850, '51.5': 399}

【讨论】:

  • 这会保留两个字典中的所有键,对吗?请您对逻辑进行更多解释
  • 是的。它正在修改 temp1,因此仅存在于 temp1 中的任何键都将保持不变,将修改 temp2 中具有较低值的任何键,并将仅存在于 temp2 中的任何键复制到 temp1,因此 temp1 以完整列表结束具有最低值的键。
【解决方案2】:

您可以通过将两个字典与公共键的最小值合并来实现字典理解:

{ **x, **y, **{k:min(x[k],y[k]) for k in x if k in y} }

输出:

{'45': 220.0, '43': 220.0, '44.5': 220.0, '39': 370.0, '47': 300.0, '46': 225.0, '44': 220.0, '47.5': 265.0, '40.5': 395.0, '42.5': 230.0, '42': 300.0, '38': 375.0, '45.5': 290.0, '37.5': 355.0, '41': 345.0, '38.5': 375.0, '36': 345.0, '36.5': 360.0, '48.5': 275.0, '40': 380.0, '48': 287, '49.5': 567, '50.5': 850, '51.5': 399, '49': 386}

或者你可以这样写(避免在大多数键是通用的情况下进行双重合并):

{ **x, **{ k:v for k,v in y.items() if k not in x or x[k]<v} }

或者,您可以对 (key,value) 元组的串联使用降序排序,但对整个数据进行排序以获得匹配键之间的最小值将非常低效:

dict(sorted((*x.items(),*y.items()),key=lambda i:-i[1]))

如果您对字典推导不满意,可以使用简单的 for 循环:

merged = x.copy()
for k,v in y.items(): merged[k] = min(v, merged.get(k,v))

【讨论】:

    【解决方案3】:

    您可以使用**kwargs 来合并字典,因为它将字典中的内容扩展为键值对的集合。我们可以对结果字典中有多个values 的keys 进行比较,

    import ast    
    
    def compare_prices(dict1, dict2):
        temp1 = ast.literal_eval(dict1)
        temp2 = ast.literal_eval(dict2)
        tempDict = {**temp1, **temp2}   # two or more Dicts merged using **kwargs
        for key, value in tempDict.items():
            if key in temp1 and key in temp2:
                tempDict[key] = min([value, temp1[key]])    # sets the minimum value
    
        return tempDict 
    

    输出

    print(compare_prices(x, y))
    #{'45': 220.0, '43': 220.0, '44.5': 220.0, '39': 370.0, '47': 300.0, '46': 225.0, '44': 220.0, '47.5': 265.0, '40.5': 395.0, '42.5': 230.0, '42': 300.0, '38': 375.0, '45.5': 290.0, '37.5': 355.0, '41': 345.0, '38.5': 375.0, '36': 345.0, '36.5': 360.0, '48.5': 275.0, '40': 380.0, '48': 287, '49.5': 567, '50.5': 850, '51.5': 399, '49': 386}
    

    如果你想要一个排序字典,你可以使用OrderedDict from collectionslibrary

    import ast
    from collections import OrderedDict
    
    def compare_prices(dict1, dict2):
        temp1 = ast.literal_eval(dict1)
        temp2 = ast.literal_eval(dict2)
        tempDict = {**temp1, **temp2}   # two or more Dicts merged using **kwargs
        for key, value in tempDict.items():
            if key in temp1 and key in temp2:
                tempDict[key] = min([value, temp1[key]])    # sets the minimum value
    
        return OrderedDict(sorted(tempDict.items(), key=lambda t: t[0]))
    

    输出

    print(compare_prices(x, y))
    #OrderedDict([('36', 345.0), ('36.5', 360.0), ('37.5', 355.0), ('38', 375.0), ('38.5', 375.0), ('39', 370.0), ('40', 380.0), ('40.5', 395.0), ('41', 345.0), ('42', 300.0), ('42.5', 230.0), ('43', 220.0), ('44', 220.0), ('44.5', 220.0), ('45', 220.0), ('45.5', 290.0), ('46', 225.0), ('47', 300.0), ('47.5', 265.0), ('48', 287), ('48.5', 275.0), ('49', 386), ('49.5', 567), ('50.5', 850), ('51.5', 399)])
    

    【讨论】:

      猜你喜欢
      • 2020-03-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-29
      • 2017-09-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多