【问题标题】:How to iterate through 2 zipped list of dictionaries under certain conditions?如何在某些条件下遍历 2 个压缩的字典列表?
【发布时间】:2021-03-11 12:00:11
【问题描述】:

字典列表有4个,前两个需要添加到数据库中,后两个已经存在于数据库中:

to_add1 = [{'name': 'Kate', 'age': 25, 'id': 1234},
           {'name': 'Claire', 'age': 25, 'id': 4567},
           {'name': 'Bob', 'age': 25, 'id': 8910}]

to_add2 = [{'pets': 5, 'name_id': 1234},
           {'pets': 0, 'name_id': 4567},
           {'pets': 0, 'name_id': 8910}]

existing1 = [{'name': 'John', 'age': 50, 'id': 0000},
             {'name': 'Claire', 'age': 25, 'id': 4567}]
existing2 = [{'pets': 2, 'name_id': 0000},
             {'pets': 0, 'name_id': 4567}]

我想添加到数据库或在这个可重现的示例中,仅打印不包含 existing1 中的 existing1['name'] 值的项目。所以在这种情况下:来自to_add1 的 Kate 和 Bob 应该打印一次。由于双循环,我得到了重复。如何循环遍历所有这些字典并打印与existing 1 名称匹配的项目而不重复?

我的代码:

for person_to_add, pet_to_add in zip(to_add1, to_add2):
    for existing_person, existing_pet in zip(existing1, existing2):
        if person_to_add['name'] not in existing_person['name']:
            print(person_to_add)

当前输出:

{'name': 'Kate', 'age': 25, 'id': 1234}
{'name': 'Kate', 'age': 25, 'id': 1234}
{'name': 'Claire', 'age': 25, 'id': 4567}
{'name': 'Bob', 'age': 25, 'id': 8910}
{'name': 'Bob', 'age': 25, 'id': 8910}

期望的输出:

{'name': 'Kate', 'age': 25, 'id': 4567}
{'name': 'Bob', 'age': 25, 'id': 8910}

【问题讨论】:

    标签: python list dictionary for-loop zip


    【解决方案1】:

    根据实际底层查询的复杂性,这可能不起作用。但这是一个利用您正在使用的字典结构列表的解决方案。我不清楚你为什么需要使用 zip。

    a = [person_to_add for person_to_add in to_add1 if person_to_add['name'] not in [existing_person['name'] for existing_person in existing1]]
    

    这使用应该非常快的列表推导。输出“a”将与所有其他数据的格式相同,即字典列表。如果您需要进一步了解列表理解的工作原理,请告诉我。

    【讨论】:

    • 您的答案是最接近的,因为我特别需要检查 ['name'] 的字典值,是否匹配 - 因此我最初制作了这两个循环。你的结果是一个列表;下一步将是再次遍历“a”,以便我可以将每个字典一个接一个地添加到数据库中(使用 Solr 和 Pysolr)。基本上,如果名称存在于 Solr 中,则不要添加字典,否则添加字典。
    • 好的,我想我明白了。我想要的是:a = [[person_to_add, pet_to_add] for person_to_add, pet_to_add in zip(to_add1, to_add2) if person_to_add['name'] not in [existing_person['name'], for existing_person in existing1]]
    • 我觉得不错。虽然我会说你必须小心使用 zip,但它可能会做一些你意想不到的事情。请注意,如果您的列表顺序不同,您会得到完全不同的结果。
    【解决方案2】:

    我假设你的意思是输出应该是Kate & Bob 因为Claireexisting1 中:

    >>> for person_to_add, pet_to_add in zip(to_add1, to_add2):
    ...     if person_to_add not in existing1:
    ...         print(person_to_add)
    ... 
    {'name': 'Kate', 'age': 25, 'id': 1234}
    {'name': 'Bob', 'age': 25, 'id': 8910}
    

    【讨论】:

      【解决方案3】:
      lst = [print(person_to_add) for person_to_add in to_add1 if person_to_add not in existing1]
      

      这可能不是最快的解决方案,但它可以完成工作。它使用python列表理解,并且易于阅读。

      正如您在问题中所描述的,您只想比较 existing1 和 to_add1 中的数据,因此您不需要使用嵌套循环来增加不必要的复杂性。使用单个循环就可以了。

      【讨论】:

      • 我专门查看 'name' 值是否匹配,而不是整个字典项是否匹配 - 您不需要第二个循环来遍历该 ['name'] 值吗?
      • 感谢您指出,我有点错过了 ['name'] ,所以这里是更新版本,它只考虑名字而不使用另一个循环。 lst = [print(person_to_add) for person_to_add in to_add1 if person_to_add['name'] not in map(lambda d: d['name'], existing1)]
      猜你喜欢
      • 1970-01-01
      • 2017-09-11
      • 2021-03-12
      • 2012-11-23
      • 2020-05-16
      • 1970-01-01
      • 2012-07-04
      • 2019-11-29
      相关资源
      最近更新 更多