繁体   English   中英

比较特定字段的两个字典列表

[英]compare two lists of dictionaries for specific fields

我有两个包含字典的列表。 我想比较每个词典中的某些字段。

current_list = [{"name": "Bill","address": "Home", "age": 23, "accesstime":11:14:01}, 
            {"name": "Fred","address": "Home", "age": 26, "accesstime":11:57:43},
            {"name": "Nora","address": "Home", "age": 33, "accesstime":11:24:14}]

backup_list = [{"name": "Bill","address": "Home", "age": 23, "accesstime":13:34:24}, 
           {"name": "Fred","address": "Home", "age": 26, "accesstime":13:34:26},
           {"name": "Nora","address": "Home", "age": 33, "accesstime":13:35:14}]

列表/词典应该按顺序相同,我只想比较某些键值对。 像名称,地址,年龄和忽略访问时间,但我到目前为止比较每个键/对。 所以我只想比较一下

current_list:dictionary[0][name] -> backup_list:dictionary[0][name] and then 
current_list:dictionary[0][address] -> backup_list:dictionary[0][address] 

等等。

for x in current_list:
    for y in backup_list:
        for k, v in x.items():
            for kk, vv in y.items():
                if k == kk:
                    print("Match: {0}".format(kk))
                    break
                elif k != kk:
                    print("No match: {0}".format(kk))

电流输出

Match name with name
No Match address with name
Match address with address
No Match age with name
No Match age with address
Match age with age
No Match dateRegistered with name
No Match dateRegistered with address
No Match dateRegistered with age
Match dateRegistered with dateRegistered

首选输出

Match name with name
Match address with address
Match age with age

*由于需求更改,我的列表成为Elementtree xml元素的列表*

因此,而不是上面的列表,它变成了

backup_list =  ["<Element 'New' at 0x0000000002698C28>, <Element 'Update' at 0x0000000002698CC8>, <Element 'New' at 0x0000000002698CC8>"]

ElementTree是一个包含以下内容的xml元素:

{"name": "Nora", "address": "Home", "age": 33, "dateRegistered": 20140812}"

所以这个基于下面的答案似乎满足我的要求到目前为止:

value_to_compare = ["name", "address", "age"]
for i, elem in enumerate(current_list):
    backup_dict = backup_list[i]
    if elem.tag == "New":
        for key in value_to_compare:
            try:
                print("Match {0} {1} == {2}:".format(key, backup_dict.attrib[key], elem.attrib[key]))
            except KeyError:
                print("key {} not found".format(key))
            except:
                raise
    else:
        continue

我不知道我是否完全理解你的问题,但我认为以下代码应该可以解决问题:

compare_arguments = ["name", "age", "address"]
for cl, bl in zip(current_list, backup_list):
    for ca in compare_arguments:
        if cl[ca] == bl[ca]:
            print("Match {0} with {0}".format(cl[ca]))
    print("-" * 10)

在上面的代码中完成的是对两个列表的zip迭代。 使用另一个列表,您可以指定要比较的字段。 在主循环中,您遍历可比较的字段并相应地打印它们。

您可以使用以下代码比较所有相应的字段:

for dct1, dct2 in zip(current_list, backup_list):
    for k, v in dct1.items():
        if k == "accesstime":
            continue
        if v == dct2[k]:
            print("Match: {0} with {0}".format(k))
        else:
            print("No match: {0} with {0}".format(k))

请注意, "accesstime"键的值不是有效的Python对象!

我不明白你的数据结构的合理性,但我认为这样做可以解决问题:

value_to_compare = ["name", "address", "age"]

for i, elem in enumerate(current_list):
    backup_dict = backup_list[i]
    for key in value_to_compare:
        try:
            print("Match {}: {} with {}".format(key, elem[key], backup_dict[key]))
        except KeyError:
            print("key {} not found".format(key))
            # may be a raise here.
        except:
            raise

如果您乐意使用第三方库,可以通过Pandas以更有条理的方式更有效地实施此类任务:

import pandas as pd

res = pd.merge(pd.DataFrame(current_list),
               pd.DataFrame(backup_list),
               on=['name', 'address', 'age'],
               how='outer',
               indicator=True)

print(res)

  accesstime_x address  age  name accesstime_y _merge
0     11:14:01    Home   23  Bill     13:34:24   both
1     11:57:43    Home   26  Fred     13:34:26   both
2     11:24:14    Home   33  Nora     13:35:14   both

结果_merge = 'both'为每行显示的组合['name', 'address', 'age']发生在两个列表,但是,除此之外,你能看到accesstime每个输入。

只需与此比较 -

for current in current_list:
    for backup in backup_list:
        for a in backup:
            for b in current:
                if a == b:
                    if a == "name" or a== "age" or a== "address" :
                        if backup[a] == current[b]:
                            print (backup[a])
                            print (current[b])

您可以使用zip方法同时迭代列表。

elements_to_compare = ["name", "age", "address"]
for dic1, dic2 in zip(current_list, backup_list):
    for element in elements_to_compare :
        if dic1[element] == dic2[element]:
            print("Match {0} with {0}".format(element))

有人已经制作了一个名为deepdiff的模块,可以做到这一点,而且还有更多! 请参阅此答案以获取详细说明!

首先 - 安装它

pip install deepdiff

然后 - 享受

#of course import it
from deepdiff import DeepDiff

current_list, backup_list = [...], [...] #values stated in question.

for c, b in zip(current_list, backup_list):
    dif = DeepDiff(c, b)
    for key in ["name", "age", "address"]:
        try:
            assert dif['values_changed'][f"root['{key}'"]
            #pass the below line to exclude any non-matching values like your desired output has
            print(f"No Match {key} with {key}")
        except KeyError:
            print(f"Match {key} with {key}")

结果: - 如预期的那样

Match name with name
Match address with address
Match age with age
Match name with name
Match address with address
Match age with age
Match name with name
Match address with address
Match age with age

最后的说明

此模块还有许多其他功能,例如type更改, key更改/删除/添加,广泛的text比较和搜索。 绝对值得一看。

~GL你的项目!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM