Python:通过其字典属性之一过滤自定义对象列表

Python: filtering a list of custom objects, by one of its dictionary attributes

我正在尝试在我的 class 中创建一个方法,该方法能够通过其字典属性之一过滤此 class 中的对象列表。例如:

在我下面创建的 class Vehicle 中,category 参数将被赋予一个字典键:值组合,如果 Vehicle 则值为 1符合该类别,即:

{'convertible': 1, 'pickup': 0, 'electric': 1}

因此,对于我的 class 车辆,我可以创建一个汽车对象列表:

class Vehicle:
    def __init__(self, name, category, price):
        self.__name = name
        self.__category = category
        self.__price = price 

lst_cars = 
[
Vehicle('Viper', {'convertible': 1, 'pickup': 0, 'electric': 1}, 300,000), 
Vehicle('x150', {'convertible': 0, 'pickup': 1, 'electric': 0}, 300,000), 
Vehicle('BMW', {'convertible': 1, 'pickup': 0, 'electric': 1}, 300,000)
] 

我可以使用 attrgetter 按名称对我的列表进行排序,并使用以下代码将名称作为 属性 传递:

def order_by(lst_cars, property):
    lst = []
    c = sorted(lst_cars, key=attrgetter(prop))
    for car in c:
        lst += [car]
    return lst

但我真正想要的是一种方法 parse_by(lst_cars, lst_category),它接受一个 Vehicle 对象列表和一个类别字符串列表 ['convertible', 'electric'],它会 return 一个列表这些类别值为 1 的对象的数量。

[
Vehicle('Viper', {'convertible': 1, 'pickup': 0, 'electric': 1}, 300,000), 
Vehicle('BMW', {'convertible': 1, 'pickup': 0, 'electric': 1}, 300,000)
]  

稍微研究一下我的代码后,我想出了以下似乎可行的方法,因此编辑了一个答案,但下面的其他人也很有帮助:

def parse_by(lst_cars, lst_category):
    c = lst_cars
    for item in lst_category:
        c = list(filter(lambda x: x.category[item] == 1, c))
    return c

这是您可能正在寻找的一个简单示例。肯定有更有效的解决方案,但现在这应该对你有帮助。请注意,我删除了属性前面的 __ 以便使用我的函数从外部访问它们。否则你将不得不写类似 obj._Vehicle__category 而不是 obj.category 来访问它们。

class Vehicle:
    def __init__(self, name, category, price):
        self.name = name
        self.category = category
        self.price = price

lst_cars = [
Vehicle('Viper', {'convertible': 1, 'pickup': 0, 'electric': 1}, 300.000),
Vehicle('x150', {'convertible': 0, 'pickup': 1, 'electric': 0}, 300.000),
Vehicle('BMW', {'convertible': 1, 'pickup': 0, 'electric': 1}, 300.000)
]

def parse_by(lst_cars, lst_category):
    output = lst_cars.copy()
    for attr in lst_category:
        for obj in output:
            if not obj.category.get(attr):
                output.remove(obj)
    return output


for x in parse_by(lst_cars, ['convertible', 'electric']):
    print(x.name)
#Viper
#BMW

让我们试试这个,

  • Vehicle class 中定义 parse_by(lst_cars = [], lst_category = []),其中 return 布尔值基于搜索过滤器。 __ 使变量私有并且在外部不可见,它只能从自己的内部访问 class.
class Vehicle:
    def __init__(self, name, category, price):
        self.__name = name
        self.__category = category
        self.__price = price

    def parse_by(self, lst_cars, lst_category):
        if self.__name in lst_cars and \
                all(self.__category.get(c) for c in lst_category):
            return True
        else:
            return False

    def __str__(self):
        return f"name : {self.__name}, cateogry : {self.__category} price : {self.__price}"
  • 使用列表理解来过滤值。
lst_cars = [
    Vehicle('Viper', {'convertible': 1, 'pickup': 0, 'electric': 1}, 300000),
    Vehicle('x150', {'convertible': 0, 'pickup': 1, 'electric': 0}, 300000),
    Vehicle('BMW', {'convertible': 1, 'pickup': 0, 'electric': 1}, 300000)
]

print(
    [str(x) for x in lst_cars if x.parse_by(['Viper', 'BMW'], ['convertible'])]
)
def parse_by(lst_cars, lst_category):
    validCars = []
    for car in lst_cars:
         if all([car.getattr(attr) for attr in lst_category]): #any applies logical ANDs on all elements in list
            validCars.append(car)
    return validCars

[car.getattr(attr) for attr in lst_category] 这会为 lst_cars.

中的特定汽车创建所有类别(属性)的值列表