【问题标题】:compare two lists of dictionaries for specific fields比较特定字段的两个字典列表
【发布时间】:2019-04-23 23:57:28
【问题描述】:

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

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

【问题讨论】:

  • 我刚刚发现我不能使用字典列表,因为我必须考虑其他一些标准。所以它实际上必须是一个 xml 元素列表。 [,,]。 RomainL 的解决方案接近我所需要的。

标签: python list dictionary


【解决方案1】:

简单对比一下——

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

【讨论】:

    【解决方案2】:

    有人已经制作了一个名为deepdiff 的模块,它可以做到这一点,而且还有更多!详细解释请参考this answer

    首先 -安装它

    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 在你的项目上!

    【讨论】:

      【解决方案3】:

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

      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 迭代。使用另一个列表,您可以指定要比较的字段。在主循环中,您遍历可比较的字段并相应地打印它们。

      【讨论】:

      • 您必须在您的compare_arguments 列表中添加"address"
      • @Ev.Kounis 我认为问题是关于仅比较可能的字典条目的一个子集。这就是我明确定义进行比较的键的原因。谢谢你的提示...
      【解决方案4】:

      您可以使用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))
      

      【讨论】:

        【解决方案5】:

        如果您乐于使用 3rd 方库,则可以通过 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

        【讨论】:

          【解决方案6】:

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

          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
          

          【讨论】:

          • 我刚刚发现我不能使用字典列表,因为我必须考虑其他一些标准。所以它实际上必须是一个 xml 元素列表。 [,,]
          • 这应该是 print("Match {}: {} with {}".format(key, elem[i], backup_dict[i])) 因为 key 是 value_to_compare 中的一个值。在哪里我会是一个整数?
          • 如果我明白了,你会想要比较xml元素吗?但仅在某些领域?我不确定您是否了解新数据,您可以更新您的问题吗?还是问一个新的?
          • 根据您的解决方案更新了我上面的答案。谢谢:)
          【解决方案7】:

          你可以用这段代码比较所有对应的字段:

          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 对象!

          【讨论】:

            猜你喜欢
            • 2021-05-26
            • 2017-08-21
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多