【问题标题】:Looping to find matching values in two dictionaries循环查找两个字典中的匹配值
【发布时间】:2019-05-13 17:27:42
【问题描述】:

我有两个由字典组成的不同文件。我正在尝试仅遍历字典第一个文件中的键 ('name') 和值,并将它们与第二个文件匹配。我似乎得到了错误的输出,因为它循环通过两个键“名称”和“大小”。我已经研究了一些这样做的方法,但我不想能够将我的字典转换为集合。我希望能够打印出“匹配”或“不匹配”。到目前为止,我已经完成了以下工作:

def compare_files():

with open('new.json', 'r') as current_data_file, open('old.json','r') as pre_data_file:

    for current_data, previous_data in zip(current_data_file, pre_data_file):

        data_current = json.loads(current_data)
        data_previous = json.loads(previous_data)



        for key, value in data_current.items():
            if value not in data_previous:
                print "No Match"
            else:
                print "Match"

这是我正在加载的两个 json 文件:

old.json

{"name": "d.json", "size": 1000}
{"name": "c.json", "size": 1000}
{"name": "b.json", "size": 1000}

新的.json

{"name": "a.json", "size": 1000}
{"name": "b.json", "size": 1000}
{"name": "c.json", "size": 1000}

data_current 是:

{u'size': 1000, u'name': u'a.json'}
{u'size': 1000, u'name': u'b.json'}
{u'size': 1000, u'name': u'c.json'}

data_previous 是:

{u'size': 1000, u'name': u'd.json'}
{u'size': 1000, u'name': u'c.json'}
{u'size': 1000, u'name': u'b.json'}

输出:

No Match
No Match
No Match
No Match
No Match
No Match

我的预期输出是:

No Match
Match
Match

b.json 和 c.json 都存在,但 a.json 和 d.json 不存在。

【问题讨论】:

  • 你试过if value not in data_previous.values():吗?这样您只需签入值而不是键和值
  • 我想只检查键 'name' 而不是 'size' 的值? @Bazingaa
  • 如果你只想检查密钥'name',你没有检查密钥。此外,if value not in data_previous 不会检查data_previous 的值,而是将data_current 中的值与data_previous 中的键进行比较
  • @sparkdev 我不确定您的预期输出是什么?我假设它不在问题中。
  • 我已经更新了我的问题@RoadRunner

标签: python json python-2.7 dictionary


【解决方案1】:

为了避免麻烦,您可以使用pandas(第三方库)直接读取数据,并且可以非常轻松地进行分析

import pandas as pd

df=pd.DataFrame('new.json')
df2=pd.DataFrame('old.json')

df.name.isin(df2.name).replace({False:'No Match',True:'Match'}).tolist()

输出

['No Match', 'Match', 'Match']

【讨论】:

    【解决方案2】:

    您的代码中有几个问题。

    1. 当您执行if value not in data_previous: 时,实际上是在检查value 是否在data_previous 中,而不是在其值中。

    2. 当您执行zip(current_data_file, pre_data_file) 时,您实际上是在查看两个字典的对应 对。在这里,您有 3 个字典,每个字典有 2 个键,这就是为什么您有 6 个输出行而不是 3 个。换句话说,您正在成对查找数据,而不是将数据中的每个字典与另一个字典中的所有其他字典进行比较数据。

    这是一个示例代码:

    def compare_files():
        with open('new.json', 'r') as current_data_file, open('old.json','r') as pre_data_file:
            # load both data 
            data_currents = [json.loads(line) for line in current_data_file]
            data_previous = [json.loads(line) for line in pre_data_file]
    
            # store the previous names for convenient lookup
            pre_names = set([data["name"] for data in data_previous])
    
            # loop through all current data for matching names
            for data in data_currents:
                print("Match" if data["name"] in pre_names else "No Match")
    

    【讨论】:

    • 我怎样才能遍历两个不同的文件而不是使用 zip。我会有一个嵌套的for循环@QuangHoang
    • 你需要做一些嵌套的事情,就像@Karl的回答一样。
    【解决方案3】:

    您必须将每个“当前”项目与所有“以前”项目进行比较,而不仅仅是与处于相同位置的项目进行比较(这是“zip”可以帮助您实现的)

    data_current = [{"name": "d.json", "size": 1000},
                    {"name": "c.json", "size": 1000},
                    {"name": "b.json", "size": 1000}]
    
    data_previous = [{"name": "a.json", "size": 1000},
                     {"name": "b.json", "size": 1000},
                     {"name": "c.json", "size": 1000}]
    
    for current in data_current:
        result = "No Match"
        for previous in data_previous:
            if current["name"] == previous["name"]:
                result = "Match"
        print(result)
    

    编辑:如果您想检查当前项目与以前的项目以及以前的项目与当前项目,您可以执行以下操作(我在打印件中添加了一些文本以阐明正在发生的事情)

    checks_to_run = [
        {
            "from": data_current,
            "from_name": "current", #Added for transparency
            "against": data_previous,
            "against_name": "previous", #Added for transparency
        },
        {
            "from": data_previous,
            "from_name": "previous", #Added for transparency
            "against": data_current,
            "against_name": "current", #Added for transparency
        }
    ]
    
    for check_to_run in checks_to_run:
        for check_from in check_to_run["from"]:
            result = "No Match"
            for check_against in check_to_run["against"]:
                if check_from["name"] == check_against["name"]:
                    result = "Match"
            print("result for item {} from {} compared to items in {}: {}".format(check_from["name"],
                                                                                  check_to_run["from_name"],
                                                                                  check_to_run["against_name"],
                                                                                  result))
    

    【讨论】:

    • 我在您的代码中看到,对于 data_current 中的值打印“不匹配”。我怎样才能打印出 data_previous 中的值的“不匹配”。它必须打印出 data_current 和 data_previous @Karl 中不存在的值
    • 在这种情况下,只需执行两次。根据之前的完整列表检查当前的每一项。然后根据当前的完整列表检查以前的每个项目。我会用一个小例子来更新我的答案
    猜你喜欢
    • 1970-01-01
    • 2012-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-03
    • 2017-05-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多