首页 > 解决方案 > 具有列表设计模式的 Python 过滤器

问题描述

我正在尝试从列表中过滤数据。它将基于配置。因此,当发生变化时 - 我将可以选择进行更改。我有一个数据对象

[
    {
        "student_id": A01,
        "student_name": "Full Name",
        "class": "one"
    },
    {
        "student_id": A01,
        "student_name": "Full Name",
        "class": "two"
    },
    {
        "student_id": A01,
        "student_name": "Full Name",
        "class": "three"
    },
    {
        "student_id": A01,
        "student_name": "Full Name",
        "class": "four"
    },
    ....
]

现在我需要筛选出他们需要class two and four和其他人需要的学校all data including all classes。我有一个像这样的课程:

// Base Class
class FilterBase(object):
    def filter_by_class(self, content):
        pass

// student filter
class StudentFilter(FilterBase):
    def __init__(self, filters=None):
        self._filters = list()
        if filters is None:
            return

    def filter_by_class(self, content):
        for filter in self._filters:
            content = filter(content)
        return content


get_class_two_four = [
      "class": "two",
      "class": "four"
]
default = [] // for default it will return full list

//filtered result 
filter_obj = StudentFilter([
            get_class_two_four
        ])

我如何获得这样的预期输出:

[
    {
        "student_id": A01,
        "student_name": "Full Name",
        "class": "two"
    },
    {
        "student_id": A01,
        "student_name": "Full Name",
        "class": "four"
    },
    ....
]

标签: pythonflask

解决方案


假设您有以下数据结构:

student_list = [
    {
        "student_id": "A01",
        "student_name": "Full Name",
        "class": "one"
    },
    {
        "student_id": "A01",
        "student_name": "Full Name",
        "class": "two"
    },
    {
        "student_id": "A01",
        "student_name": "Full Name",
        "class": "three"
    },
    {
        "student_id": "A01",
        "student_name": "Full Name",
        "class": "four"
    }
]

class_set = {"two", "four"}

您可以实现一个student_in_classes帮助函数,告诉您学生是否在过滤的班级之一中。如果班级过滤器为空,则只返回所有学生。


class FilterBase(object):
    def __init__(self, filters : set = set()):
        self._filters = filters

class StudentFilter(FilterBase):
    def __init__(self, class_set : set = set()):
        super().__init__(class_set)

    def filter_by_class(self, student_data : list):
        # No point in filtering if nothing to filter on
        return student_data if not self._filters else list(filter(self.student_in_classes, student_data))

    # When student's class matches a filter, this will return True
    def student_in_classes(self, student_dict : dict):
       # Using .get() to handle cases where class isn't provided
       return student_dict.get("class", None) in self._filters

这将允许您执行以下操作:

sf_no_filter = StudentFilter()
sf_2_filters = StudentFilter(class_set)
print(sf_no_filter.filter_by_class(student_list)) # No filter provided
print(sf_2_filters.filter_by_class(student_list)) # 2 class filters

与输出

# No Filter Provided
[
    {
        "student_id": "A01",
        "student_name": "Full Name",
        "class": "one"
    },
    {
        "student_id": "A01",
        "student_name": "Full Name",
        "class": "two"
    },
    {
        "student_id": "A01",
        "student_name": "Full Name",
        "class": "three"
    },
    {
        "student_id": "A01",
        "student_name": "Full Name",
        "class": "four"
    }
]


# Classes "two" and "four" provided
[
    {
        "student_id": "A01",
        "student_name": "Full Name",
        "class": "two"
    },
    {
        "student_id": "A01",
        "student_name": "Full Name",
        "class": "four"
    }
]

根据您的要求/实现,让构造函数同时接受类过滤器和学生列表可能更有意义,这样您就可以get_filtered()在您的实例上创建/调用一个简单的StudentFilter返回相同的事情filter_by_class()

此外,为了命名类,命名它可能更有意义ClassFilterStudentFilter因为类是每个实例的静态过滤标准。


推荐阅读