Skip to main content
 首页 » 编程设计

python之如何用另一个词典列表过滤词典列表

2025年05月04日19落叶无声

我想用 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 列表的结构?

请您参考如下方法:

鉴于 vehicle.make 与 value 等不同,您的过滤不会返回 False

您可以将过滤器重写为:

def filter_item(vehicle, filters): 
    for fil in filters: 
        key = fil['type'] 
        value = fil['value'] 
        if key == 'make': 
            if <b>vehicle.make != value</b>: 
                <b>return False</b> 
        elif key == 'model': 
            if <b>vehicle.model != value</b>: 
                <b>return False</b> 
        else: 
            return False 
    return True

或者我们可以使用getattr:

def filter_item(vehicle, filters): 
    for fil in filters: 
        if <b>fil['value'] != getattr(vehicle, fil['type'])</b>: 
            return False 
    return True

或使用 all(..) [python-doc] :

def filter_item(vehicle, filters): 
    return <b>all(</b>fil['value'] == getattr(vehicle, fil['type']) for fil in filters<b>)</b>

如果您打算过滤 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].