【问题标题】:Compare 2 list of dictionnary based on selected key without for loop根据所选键比较 2 个字典列表,无需 for 循环
【发布时间】:2021-11-29 09:53:41
【问题描述】:

假设我有这 2 个字典列表:

Dict1=[
    {"name": "James","age": "21"},
    {"name": "Evelyn","age": "28"},
    {"name": "William","age": "31"}
]

Dict2=[
    {"name": "James","age": "21","city":"NYC","Gender":"M"},
    {"name": "William","age": "25","city":"NYC","Gender":"M"},
    {"name": "Ella","age": "17","city":"NYC","Gender":"F"}
]

如何仅根据名称键比较它们并从 dict2 获取整个条目,在这种情况下,结果必须是:

new_dict=[
    {"name": "James","age": "21","city":"NYC","Gender":"M"},
    {"name": "William","age": "25","city":"NYC","Gender":"F"},
]

我正在寻找一种方法来根据一个或多个选定的键进行比较,而不使用 for 循环。

【问题讨论】:

  • 为什么要避免循环?这是实现这一目标的最简单、最明显的方法。
  • 如果不循环或重新组织数据,您想要什么是不可能的
  • 正如至少一个答案中所说:您有 dicts 列表。您没有两个字典,而是两个列表。

标签: python list dictionary compare


【解决方案1】:

如果没有循环,你想做的事情是不可能的。您最终可以通过使用库或复杂的方式隐藏循环,但最简单的是循环。

现在有坏方法和好方法循环。不好的做法是检查 Dict1 的每个元素与 Dict2 的每个元素(O(n*m) 复杂度)。

一个好的方法是为 Dict1 中的名称构建一个 set 索引,并使用它们来匹配 Dict2 的名称:

names = set(d['name'] for d in Dict1)
new_dict = [d for d in Dict2 if d['name'] in names]

输出:

>>> new_dict
[{'name': 'James', 'age': '21', 'city': 'NYC', 'Gender': 'M'},
 {'name': 'William', 'age': '25', 'city': 'NYC', 'Gender': 'M'}]

【讨论】:

  • 谢谢@mozway,这也是一个很好的解决方案,但我的技术主管禁止我使用 for 循环。
  • @Med 那么请在你得到答案后回来。我很想知道无循环解决方案是什么。我的猜测,某处会涉及到一个循环,但隐藏起来;)
  • 好的,我会和你联系
  • 最后我说服他,没有for循环很难解决这个问题。
  • 感谢@Med 的反馈;)那么您的讲师的解决方案是什么?
【解决方案2】:
  1. 为清楚起见,您将列表命名为“字典”。这可能会在未来变得令人困惑。
  2. 假设名称是唯一的,您可以像这样使用字典:
d1 = {person['name']: person for person in Dict1}
d2 = {person['name']: person for person in Dict2}
result = [person for name, person in d2.items() if name in d1]
# result is:
[
  {'name': 'James', 'age': '21', 'city': 'NYC', 'Gender': 'M'},
  {'name': 'William', 'age': '25', 'city': 'NYC', 'Gender': 'M'}
]

还有其他方法可以实现这一点,有些甚至更有效,但如果您需要可读性,这可能会有所帮助。

编辑:这显然使用了循环,但是如果不迭代集合,就无法完成您的请求。所以我假设你只是想避免 for 块。

【讨论】:

    【解决方案3】:

    有点复杂,但您可以使用 pandas 来避免使用循环:

    import pandas as pd
    Dict1=[
        {"name": "James","age": "21"},
        {"name": "Evelyn","age": "28"},
        {"name": "William","age": "31"}
    ]
    
    Dict2=[
        {"name": "James","age": "21","city":"NYC","Gender":"M"},
        {"name": "William","age": "25","city":"NYC","Gender":"M"},
        {"name": "Ella","age": "17","city":"NYC","Gender":"F"}
    ]
    
    df1 = pd.DataFrame(Dict1)
    df2 = pd.DataFrame(Dict2)
    
    df = df2[df2['name'].isin(df1['name'])]
    print(df.to_dict(orient="records"))
    

    输出:

    [{'name': 'James', 'age': '21', 'city': 'NYC', 'Gender': 'M'}, {'name': 'William', 'age': '25', 'city': 'NYC', 'Gender': 'M'}]
    

    【讨论】:

    • 值得强调的是,这实现了不在代码中使用for 的目标,但pandas 仍将在幕后循环(如果目标是更哲学的目标)编程风格)。
    • 谢谢@Tranbi
    猜你喜欢
    • 2021-05-26
    • 1970-01-01
    • 2019-10-02
    • 1970-01-01
    • 2013-07-18
    • 2013-01-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多