我有一个很大的数据集(字典列表 - 我称之为 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)
答案 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();
}
列表以查找每个过滤器的匹配项。前两个答案有类似的问题。
在这些情况下,您通常可以通过将其中一个列表转换为字典或集合来大大提高速度。这样您只需扫描每个列表一次。
ds
中出现一次;ds
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
查找)。
dict
和 ds
中都有重复项,或者如果您需要使用不同的过滤器列表重复多次,那么您需要创建一个查找字典,将其中的多个元素分组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