我想用Python和Django中的另一个字典列表过滤字典列表。
我有一个过滤器列表,如下所示:
filters = [{'type': 'make', 'value': 'SEAT'}, {'type': 'model', 'value': 'Acura'}]
我的车辆清单如下:
vehicles = [
{'make': 'Audi', 'model': 'A3', 'transmission': 'Manual'},
{'make': 'Audi', 'model': 'A1', 'transmission': 'Automatic'},
{'make': 'Seat', 'model': 'Acura', 'transmission': 'Manual'},
{'make': 'Seat', 'model': 'LEON', 'transmission': 'Manual'},
{'make': 'Skoda', 'model': 'Octavia', 'transmission': 'Manual'},
]
我想获取所有带有make Seat
和model Acura
的车辆。因此,我想要的结果是:
[
{'make': 'Seat', 'model': 'Acura', 'transmission': 'Manual'}
]
我尝试了如下操作:
def filter_item(vehicle, filters):
for fil in filters:
key = fil['type']
value = fil['value']
if key == 'make':
if vehicle.make == value:
continue
elif key == 'model':
if vehicle.model == value:
continue
else:
return False
return True
vehicles = list(filter(lambda vehicle: filter_item(vehicle, filters), vehicles))
但这给了我所有的车辆。
有什么主意吗?
更新
因此,如果我具有以下过滤器:
filters = [
{'type': 'make', 'value': 'SEAT'},
{'type': 'model', 'value': 'Acura'},
{'type': 'model', 'value': 'LEON'}
]
我想要下一个结果:
[
{'make': 'Seat', 'model': 'Acura', 'transmission': 'Manual'},
{'make': 'Seat', 'model': 'LEON', 'transmission': 'Manual'},
]
我该怎么做?
我是否需要更改filters
列表的结构?
答案 0 :(得分:3)
鉴于False
与vehicle.make
不相同,您的过滤不会返回value
,等等。
您可以将过滤器重写为:
def filter_item(vehicle, filters):
for fil in filters:
key = fil['type']
value = fil['value']
if key == 'make':
if vehicle.make != value:
return False
elif key == 'model':
if vehicle.model != value:
return False
else:
return False
return True
或者我们可以利用getattr
:
def filter_item(vehicle, filters):
for fil in filters:
if fil['value'] != getattr(vehicle, fil['type']):
return False
return True
def filter_item(vehicle, filters):
return all(fil['value'] == getattr(vehicle, fil['type']) for fil in filters)
如果您打算过滤Django记录,但是我强烈建议对数据库进行尽可能多的过滤,因为数据库已针对此任务进行了优化。
编辑:您可以合并同一字段的析取词。例如,通过预处理过滤器:
from collections import defaultdict
filter_dict = defaultdict(set)
for fil in filters:
filter_dict[fil['type']].add(fil['value'])
def filter_item(vehicle):
return all(getattr(vehicle, k) in v for k, v in filter_dict.items())
如果您的vehicle
不是带有属性的对象,而是字典,则应将getattr(vehicle, k)
替换为vehicle[k]
。
答案 1 :(得分:2)
vehicles = [
{'make': 'Audi', 'model': 'A3', 'transmission': 'Manual'},
{'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 = [
{'type': 'make', 'value': 'Seat'},
{'type': 'model', 'value': 'Acura'},
{'type': 'model', 'value': 'LEON'}
]
filters_ = dict.fromkeys(vehicles[0].keys(), tuple())
for filt in filters:
filters_[filt['type']] += (filt['value'],)
[vehicle for vehicle in vehicles
if all((vehicle[key] in val or not val) for key, val in filters_.items())]
Out[17]:
[{'make': 'Seat', 'model': 'Acura', 'transmission': 'Manual'},
{'make': 'Seat', 'model': 'LEON', 'transmission': 'Manual'}]