【问题标题】:Compare list of dictionaries with variable number of dictionaries in each list将字典列表与每个列表中可变数量的字典进行比较
【发布时间】:2020-04-21 15:17:24
【问题描述】:

我有两个字典列表:

list1 = [
    {'vehicle': 1, 'mileage': 25, 'speed': 80}, 
    {'vehicle': 2, 'mileage': 35, 'speed': 70},
    {'vehicle': 3, 'mileage': 40, 'speed': 90},
    {'vehicle': 5, 'mileage': 40, 'speed': 90}
]

list2 = [
    {'vehicle': 1, 'mileage': 35, 'speed': 80}, 
    {'vehicle': 2, 'mileage': 35, 'speed': 70},
    {'vehicle': 3, 'mileage': 40, 'speed': 80},
    {'vehicle': 4, 'mileage': 40, 'speed': 80}
]

如果 list2 上有同名车辆并且相应车辆的里程和速度大于或等于 list2 中的,我必须从 list1 打印字典。 在这个例子中,输出应该是:

[{'vehicle': 1, 'mileage': 25, 'speed': 80}, 
 {'vehicle': 2, 'mileage': 35, 'speed': 70}]

非常感谢任何帮助。

【问题讨论】:

  • 你试过什么?您可以嵌套两个循环并检查当前值是否符合您的要求。如果这是真的,请将值添加到一个空列表中,否则继续。

标签: python python-3.x dictionary


【解决方案1】:

您可以创建一个查找字典来搜索 O(1) 中的相应匹配项:

list1 = [{'vehicle': 1, 'mileage': 25, 'speed': 80},
         {'vehicle': 2, 'mileage': 35, 'speed': 70},
         {'vehicle': 3, 'mileage': 40, 'speed': 90},
         {'vehicle': 5, 'mileage': 40, 'speed': 90}]

list2 = [{'vehicle': 1, 'mileage': 35, 'speed': 80},
         {'vehicle': 2, 'mileage': 35, 'speed': 70},
         {'vehicle': 3, 'mileage': 40, 'speed': 80},
         {'vehicle': 4, 'mileage': 40, 'speed': 80}]


lookup = {e['vehicle'] : e for e in list1 }

result = []
for e in list2 :
    if e['vehicle'] in lookup:
        d = lookup[e['vehicle']]
        if e['mileage'] >= d['mileage'] and e['speed'] >= d['speed']:
            result.append(d)

print(result)

输出

[{'vehicle': 1, 'mileage': 25, 'speed': 80}, {'vehicle': 2, 'mileage': 35, 'speed': 70}]

使用list comprehension 的替代方法:

def better(e, d, keys=('mileage', 'speed')):
    return all(e[k] >= d[k] for k in keys)


result = [lookup[e['vehicle']] for e in list2 if e['vehicle'] in lookup and better(e, lookup[e['vehicle']])]

print(result)

这两种方法的总体复杂度为O(n)

【讨论】:

    【解决方案2】:

    我会使用熊猫数据框。 不是最有效但非常易读

    import pandas as pd
    df1 = pd.DataFrame(list1)
    df2 = pd.DataFrame(list2)
    result_df = df1[(df1.vehicle.isin(df2.vehicle)) & (df1.speed <= df2.speed) & (df1.mileage <= df2.mileage)]
    result_list = result_df.to_dict('records')
    
    print(result_list)
    

    输出:

    [{'mileage': 25, 'speed': 80, 'vehicle': 1},
     {'mileage': 35, 'speed': 70, 'vehicle': 2}]
    

    【讨论】:

      【解决方案3】:

      您可以将字典列表转换为嵌套字典,其中vehicle 是关键:

      list1 = [
          {"vehicle": 1, "mileage": 25, "speed": 80},
          {"vehicle": 2, "mileage": 35, "speed": 70},
          {"vehicle": 3, "mileage": 40, "speed": 90},
          {"vehicle": 5, "mileage": 40, "speed": 90},
      ]
      
      list2 = [
          {"vehicle": 1, "mileage": 35, "speed": 80},
          {"vehicle": 2, "mileage": 35, "speed": 70},
          {"vehicle": 3, "mileage": 40, "speed": 80},
          {"vehicle": 4, "mileage": 40, "speed": 80},
      ]
      
      dict1 = {x["vehicle"]: x for x in list1}
      # {1: {'vehicle': 1, 'mileage': 25, 'speed': 80}, 2: {'vehicle': 2, 'mileage': 35, 'speed': 70}, 3: {'vehicle': 3, 'mileage': 40, 'speed': 90}, 5: {'vehicle': 5, 'mileage': 40, 'speed': 90}}
      
      dict2 = {x["vehicle"]: x for x in list2}
      # {1: {'vehicle': 1, 'mileage': 35, 'speed': 80}, 2: {'vehicle': 2, 'mileage': 35, 'speed': 70}, 3: {'vehicle': 3, 'mileage': 40, 'speed': 80}, 4: {'vehicle': 4, 'mileage': 40, 'speed': 80}}
      

      然后取键的交集并使用list comprehension将结果作为字典列表返回:

      result = [
          dict1[k]
          for k in dict1.keys() & dict2.keys()
          if dict2[k]["mileage"] >= dict1[k]["mileage"]
          and dict2[k]["speed"] >= dict1[k]["speed"]
      ]
      
      print(result)
      

      输出:

      [{'vehicle': 1, 'mileage': 25, 'speed': 80}, {'vehicle': 2, 'mileage': 35, 'speed': 70}]
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-11-07
        • 1970-01-01
        • 2017-06-21
        • 2019-03-24
        • 1970-01-01
        • 2022-09-23
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多