使用另一个字典列表过滤字典列表

时间:2021-06-22 09:07:14

标签: python dictionary

我有一个很大的数据集(字典列表 - 我称之为 ds),我需要用另一个字典列表过滤它(我称之为过滤器)。

我正在使用另一个问题的虚拟示例作为我的基础,遗憾的是找不到答案:

编辑:存在多个具有相同品牌和型号的元素

ds = [
  {'make': 'Audi', 'model': 'A3', 'transmission': 'Manual'},
  {'make': 'Audi', 'model': 'A3', 'transmission': 'Automatic'},
  {'make': 'Audi', 'model': 'A1', 'transmission': 'Automatic'},
  {'make': 'Seat', 'model': 'Acura', 'transmission': 'Manual'},
  {'make': 'Seat', 'model': 'LEON', 'transmission': 'Manual'},
  {'make': 'Skoda', 'model': 'Octavia', 'transmission': 'Manual'},
]

filters = [
  {'make': 'Audi', 'model': 'A3'},
  {'make': 'Seat', 'model': 'LEON'},
  {'make': 'Skoda', 'model': 'Octavia'},
]

想要的输出:

ds_filtered = [
  {'make': 'Audi', 'model': 'A3', 'transmission': 'Manual'},
  {'make': 'Audi', 'model': 'A3', 'transmission': 'Automatic'},
  {'make': 'Seat', 'model': 'LEON', 'transmission': 'Manual'},
  {'make': 'Skoda', 'model': 'Octavia', 'transmission': 'Manual'},
]

这是我到目前为止编写的代码,但我想避免循环,因为数据集很大并且我希望该过程更高效:

ds_filtered = []
for f in filters:
    ds_filtered += [d for d in ds if (d['make'] == f['make'] and d['model'] == f['model'])]

print(ds_filtered)

3 个答案:

答案 0 :(得分:2)

如果您不想使用“循环”,那么“过滤器”也可以使用,假设您可以找到一些安全的方法来对 make+model 进行散列(我使用了串联,这可能会导致冲突)

filtered = list(filter(lambda elem: elem['make']+elem['model'] in [f['make']+f['model'] for f in filters], ds))

答案 1 :(得分:2)

您已经意识到,您的方法效率很低,因为它必须搜索整个 LoginPage loginPage = new LoginPage(); public void userLoginPage() { loginPage.enterUsername(); loginPage.enterPassword(); } 列表以查找每个过滤器的匹配项。前两个答案有类似的问题。

在这些情况下,您通常可以通过将其中一个列表转换为字典或集合来大大提高速度。这样您只需扫描每个列表一次。

  1. 下面是一些简单的代码,如果每个品牌/型号只在 ds 中出现一次;
ds
  1. 如果您在 dds = {(d['make'], d['model']): d for d in ds} ds_filtered = [ dds[d['make'], d['model']] for d in filters ] 中可能有重复但在 ds 中没有,您可以像这样切换:
filters

请注意,第二个创建了一个 fs = {(d['make'], d['model']) for d in filters} ds_filtered = [ d for d in ds if (d['make'], d['model']) in fs ] 来保存所有过滤器的信息。与 set 不同,它可以立即搜索以测试 list 中的每个项目(类似于 ds 查找)。

  1. 如果您可能在 dictds 中都有重复项,或者如果您需要使用不同的过滤器列表重复多次,那么您需要创建一个查找字典,将其中的多个元素分组filters 按品牌和型号。这有点复杂,但也不太难:
ds

此处的任何解决方案都需要 # make a dictionary with (make, model) as the key and # a list of all matching items from `ds` as the value dds = {} for d in ds: # add an empty list to the dictionary if needed, # then append the current element dds.setdefault((d['make'], d['model']), []).append(d) # find all the elements that match each filter ds_filtered = [ d for f in filters for d in dds[f['make'], f['model']] # if some filters may not have matches, use this instead: # for d in dds.get((f['make'], f['model']), []) ] 步。其他解决方案需要 len(ds) + len(filters) 步。

答案 2 :(得分:-2)

很简单。首先循环 ds,然后循环过滤器以查看是否有匹配项。

result = []
 for i in ds:
     for j in filters:
         if j['make'] == i['make'] and j['model'] == i['model']:
             result.append(i)
             break