蟒。按相似项目比较和合并词典列表(多样化)

Python. Compare and merge lists of dictionaries(diversed) by similar items

提问人:Sharmat 提问时间:7/24/2023 最后编辑:Sharmat 更新时间:7/24/2023 访问量:65

问:

我有两个词典列表(lod)。如果它们具有相似的项目(通过键和 ),我想比较和合并它们,如果没有将某些默认值(0)与某些 key() 设置为第一个 lod。'id''size''count'

lod1 = [{'id':1, 'size':1, 'colour':'a'}, {'id':1, 'size':2, 'colour':'ab'}, {'id':2, 'size':1, 'colour':'ab'}, {'id':2, 'size':2, 'colour':'ab'}]
lod2 = [{'id':1, 'size':1, 'count':1}, {'id':1, 'size':2, 'count':2}, {'id':2, 'size':1, 'count':3}]

输出:

merged = [{'id':1, 'size':1, 'colour':'a', 'count': 1}, {'id':1, 'size':2, 'colour':'ab', 'count': 2},  {'id':2, 'size':1, 'colour':'ab', 'count':3}, {'id':2, 'size':2, 'colour':'ab', 'count': 0}]

我提请你注意{'id':2 , 'size':2, 'colour':'ab', 'count': 0}

关于比较和合并 lod 有很多类似的问题和解决方案,但并不相同。我知道这样做的方法,但它看起来太笨重、笨拙和不优雅了。

我的解决方案:

def merge(l1, l2):
    lod1_pairs = [(i['id'], i['size']) for i in l1]
    lod2_pairs = [(i['id'], i['size']) for i in l2]
    mismatched = [pair for pair in lod1_pairs if pair not in lod2_pairs] 
    # we get list of unique pairs of lod1 to set default value to 'count' key.
    
    merged = []
    for i in lod1:
        if (i['id'], i['size']) in mismatched:
            #immediately cut off and evaluate 'count' key for the mismatched keys
            temp_dict = i| {'count': 0} 
            merged.append(temp_dict)
        else:
            for j in lod2:
                    #straightly compare key values
                    if i['id'] == j['id'] and i['size'] == j['size']:
                        temp_dict = i | j #merge dicts
                        merged.append(temp_dict)
    return merged


lod1 = [{'id':1, 'size':1, 'colour':'a'}, {'id':1 , 'size':2, 'colour':'ab'}, {'id':2, 'size':1, 'colour':'ab'}, {'id':2, 'size':2, 'colour':'ab'}]
lod2 = [{'id':1, 'size':1, 'count':1}, {'id':1, 'size':2, 'count':2}, {'id':2, 'size':1, 'count':3}]
merged = merge(lod1,lod2)

我有过使用 defaultdict 的经验,并查看了一个 DeepDiff 库,但不明白如何在这里使用它们。

Python 字典 嵌套列表 defaultdict deep-diff

评论

0赞 Andrej Kesely 7/24/2023
你能再解释一下吗?为什么在结果中缺少例如?{'id':2, 'size':1, 'colour':'ab'}count
0赞 Sharmat 7/24/2023
@AndrejKesely对不起,这是错别字,修复了它。换句话说,如果您在两个列表中都有具有相似“id”和“size”值的字典,请将其合并到新列表中并将其添加到新列表中。如果您有唯一的一对 和 ,则更新相应的字典并将其附加到相同的新列表中,例如{'id':1, 'size':1, 'colour':'a'}{'id':1, 'size':1, 'count':1}{'id':1, 'size':1, 'colour':'a', count':1}'id''size'lod1{'count':0}{'id':2, 'size':2, 'colour':'ab'} --> {'id':2, 'size':2, 'colour':'ab', 'count':0}

答:

1赞 Andrej Kesely 7/24/2023 #1

您可以尝试:

out = {(d["id"], d["size"]): {**d, "count": 0} for d in lod1}
for d in lod2:
    t = d["id"], d["size"]
    if t in out:
        out[t]["count"] = d["count"]
    else:
        out[t] = d

print(list(out.values()))

指纹:

[
    {"id": 1, "size": 1, "colour": "a", "count": 1},
    {"id": 1, "size": 2, "colour": "ab", "count": 2},
    {"id": 2, "size": 1, "colour": "ab", "count": 3},
    {"id": 2, "size": 2, "colour": "ab", "count": 0},
]
1赞 Maria K 7/24/2023 #2

版本略有不同,不使用 if..还:

def merge(lod1, lod2):
    dod2 = {(dct['id'], dct['size']): dct['count'] for dct in lod2}
    merged = []
    for entry in lod1:
        merged.append(entry)
        merged[-1]['count'] = dod2.get((entry['id'], entry['size']), 0)
    
    return merged

merge(lod1, lod2)

输出:

[{'id': 1, 'size': 1, 'colour': 'a', 'count': 1},
 {'id': 1, 'size': 2, 'colour': 'ab', 'count': 2},
 {'id': 2, 'size': 1, 'colour': 'ab', 'count': 3},
 {'id': 2, 'size': 2, 'colour': 'ab', 'count': 0}]

评论

0赞 Sharmat 7/28/2023
Спасибо, Мария!
0赞 Maria K 7/28/2023
Рада помочь!:)