介绍
Python 内置的 filter()
函数可用于从现有的可迭代对象(如 list 或 dictionary)创建新的迭代器,使用我们提供的一个功能。 iterable 是一个可以“迭代”的 Python 对象,也就是说,它将按顺序返回项目,以便我们可以在 for
循环中使用它。
filter()
函数的基本语法是:
filter(function, iterable)
这将返回一个过滤器对象,它是一个可迭代的。 我们可以使用 list()
之类的函数来列出过滤器对象中返回的所有项目。
filter()
函数提供了一种过滤值的方法,通常比 列表理解 更有效,尤其是当我们开始处理更大的数据集时。 例如,列表推导将创建一个新列表,这将增加该处理的运行时间。 这意味着在我们的列表推导完成其表达式后,我们将在内存中拥有两个列表。 但是,filter()
将创建一个简单的对象,其中包含对原始列表的引用、提供的函数以及原始列表中的位置索引,这将占用更少的内存。
在本教程中,我们将回顾使用 filter()
的四种不同方式:使用两种不同的可迭代结构,使用 lambda
函数,以及没有定义函数。
将 filter()
与函数一起使用
filter()
的第一个参数是 函数,我们用它来决定是包含还是过滤掉每个项目。 对于作为第二个参数传递的迭代中的每个项目,该函数都会调用一次,并且每次返回 False
时,都会删除该值。 由于这个参数是一个函数,我们可以传递一个普通函数,也可以使用 lambda
函数,特别是当表达式不太复杂时。
以下是带有 filter()
的 lambda
的语法:
filter(lambda item: item[] expression, iterable)
使用如下所示的列表,我们可以将 lambda
函数与我们想要评估列表中每个项目的表达式合并:
creature_names = ['Sammy', 'Ashley', 'Jo', 'Olly', 'Jackie', 'Charlie']
要过滤此列表以查找以元音开头的水族馆生物的名称,我们可以运行以下 lambda
函数:
print(list(filter(lambda x: x[0].lower() in 'aeiou', creature_names)))
在这里,我们将列表中的一个项目声明为 x
。 然后我们将表达式设置为访问每个字符串的第一个字符(或字符“零”),因此 x[0]
。 降低每个名称的大小写确保这将匹配我们表达式中的字符串 'aeiou'
中的字母。
最后我们传递了可迭代的 creature_names
。 与上一节一样,我们将 list()
应用于结果,以便从迭代器 filter()
返回创建一个列表。
输出将如下:
Output['Ashley', 'Olly']
使用我们定义的函数可以实现相同的结果:
creature_names = ['Sammy', 'Ashley', 'Jo', 'Olly', 'Jackie', 'Charlie'] def names_vowels(x): return x[0].lower() in 'aeiou' filtered_names = filter(names_vowels, creature_names) print(list(filtered_names))
我们的函数 names_vowels
定义了我们将实现过滤 creature_names
的表达式。
同样,输出如下:
Output['Ashley', 'Olly']
总的来说,lambda
函数使用 filter()
获得的结果与我们使用常规函数时相同。 随着用于过滤数据的表达式的复杂性增加,定义正则函数的必要性也在增加,这可能会提高我们代码的可读性。
将 None
与 filter()
一起使用
我们可以将 None
作为第一个参数传递给 filter()
以让返回的迭代器过滤掉 Python 认为“虚假”的任何值。 通常,Python 将长度为 0
的任何内容(例如空列表或空字符串)或数值上等同于 0
的任何内容都视为假,因此使用了“假”一词。
在以下情况下,我们希望过滤列表以仅显示水族箱中的水族箱编号:
aquarium_tanks = [11, False, 18, 21, "", 12, 34, 0, [], {}]
在这段代码中,我们有一个包含 整数 、空序列和 布尔值 的列表。
filtered_tanks = filter(None, aquarium_tanks)
我们将 filter()
函数与 None
一起使用,并将 aquarium_tanks
列表作为我们的迭代传递。 由于我们已将 None
作为第一个参数传递,因此我们将检查列表中的项目是否被认为是错误的。
print(list(filtered_tanks))
然后我们将 filtered_tanks
包装在 list()
函数中,以便在打印时返回 filtered_tanks
的列表。
这里的输出只显示整数。 所有评估为 False
的项目,其长度等于 0
,被 filter()
删除:
Output[11, 25, 18, 21, 12, 34]
注意:如果我们不使用 list()
并打印 filtered_tanks
,我们将收到类似这样的过滤器对象:<filter object at 0x7fafd5903240>
。 过滤器对象是一个可迭代对象,因此我们可以使用 for how-to-construct-for-loops-in-python-3 循环它,或者我们可以使用 list()
将它变成一个列表,我们在这里这样做是因为它是一个很好的方法审查结果。
对于 None
,我们使用 filter()
快速从列表中删除被认为是错误的项目。
将 filter()
与字典列表一起使用
当我们有更复杂的数据结构时,我们仍然可以使用 filter()
来评估每个项目。 例如,如果我们有一个字典列表,我们不仅要遍历列表中的每个项目(其中一个字典),而且我们可能还想遍历字典中的每个键:值对以评估所有的数据。
例如,假设我们有一个水族馆中每个生物的列表以及每个生物的不同细节:
aquarium_creatures = [ {"name": "sammy", "species": "shark", "tank number": "11", "type": "fish"}, {"name": "ashley", "species": "crab", "tank number": "25", "type": "shellfish"}, {"name": "jo", "species": "guppy", "tank number": "18", "type": "fish"}, {"name": "jackie", "species": "lobster", "tank number": "21", "type": "shellfish"}, {"name": "charlie", "species": "clownfish", "tank number": "12", "type": "fish"}, {"name": "olly", "species": "green turtle", "tank number": "34", "type": "turtle"} ]
我们想通过我们提供给函数的搜索字符串来过滤这些数据。 为了让 filter()
访问每个字典和字典中的每个项目,我们构造了一个嵌套函数,如下所示:
def filter_set(aquarium_creatures, search_string): def iterator_func(x): for v in x.values(): if search_string in v: return True return False return filter(iterator_func, aquarium_creatures)
我们定义了一个 filter_set()
函数,它以 aquarium_creatures
和 search_string
作为参数。 在 filter_set()
中,我们将 iterator_func()
作为函数传递给 filter()
。 filter_set()
函数将返回由 filter()
生成的迭代器。
iterator_func()
将 x
作为参数,它表示我们列表中的一个项目(即单个字典)。
接下来 for
循环访问我们字典中每个 key:value 对中的值,然后使用条件语句检查 search_string
是否在 v
中,表示一个值。
与我们之前的示例一样,如果表达式的计算结果为 True
,则该函数将该项添加到过滤器对象中。 这将在 filter_set()
函数完成后返回。 我们将 return False
定位在循环之外,以便它检查每个字典中的每个项目,而不是在单独检查第一个字典后返回。
我们调用 filter_set()
与我们的字典列表和我们想要找到匹配的搜索字符串:
filtered_records = filter_set(aquarium_creatures, "2")
函数完成后,我们将过滤器对象存储在 filtered_records
变量中,我们将其转换为列表并打印:
print(list(filtered_records))
我们将从该程序中收到以下输出:
Output[{'name': 'ashley', 'species': 'crab', 'tank number': '25', 'type': 'shellfish'}, {'name': 'jackie', 'species': 'lobster', 'tank number': '21', 'type': 'shellfish'}, {'name': 'charlie', 'species': 'clownfish', 'tank number': '12', 'type': 'fish'}]
我们使用搜索字符串 2
过滤了字典列表。 我们可以看到已经返回了包含带有 2
的坦克编号的三个字典。 使用我们自己的嵌套函数,我们可以访问每个项目并根据搜索字符串有效地检查每个项目。
结论
在本教程中,我们学习了在 Python 中使用 filter()
函数的不同方法。 现在,您可以将 filter()
与您自己的函数、lambda
函数或 None
一起使用来过滤具有不同数据结构复杂性的项目。
尽管在本教程中,我们立即以列表格式打印了 filter()
的结果,但在我们的程序中,我们可能会使用返回的 filter()
对象并进一步操作数据。
如果您想了解更多 Python,请查看我们的 How To Code in Python 3 系列和我们的 Python 主题页面。