使用另一个词典列表筛选词典列表

2024-09-22 16:27:18 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个很大的数据集(字典列表-我称之为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)

Tags: 数据makemodel字典dsmanualautomatica3
3条回答

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

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

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

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

正如您所意识到的,您的方法效率很低,因为它必须搜索整个ds列表以查找每个筛选器的匹配项。前两个答案有一个类似的问题

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

  1. 下面是一些简单的代码,如果每个make/模型只在ds中运行一次
dds = {(d['make'], d['model']): d for d in ds}
ds_filtered = [
    dds[d['make'], d['model']] 
    for d in filters
]
  1. 如果在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中的每个项目(类似于dict查找)

  1. 如果在dsfilters中可能都有重复项,或者如果需要使用不同的筛选器列表重复多次,则需要创建一个查找字典,根据make和model对来自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)步骤。其他解决方案需要len(ds) * len(filters)步骤

相关问题 更多 >