介绍
Python 内置filter()
函数可用于从现有的可迭代对象(如列表或字典)创建一个新的迭代器,该迭代器将使用我们提供的函数有效地过滤掉元素。一个可迭代对象是一个可以“迭代”的 Python 对象,也就是说,它将按顺序返回项目,以便我们可以在for
循环中使用它。
该filter()
函数的基本语法是:
filter(function, iterable)
这将返回一个过滤器对象,它是一个可迭代的。我们可以使用像这样的函数list()
来列出过滤器对象中返回的所有项目。
该filter()
函数提供了一种过滤值的方法,通常比列表理解更有效,尤其是当我们开始处理更大的数据集时。例如,列表推导将创建一个新列表,这将增加该处理的运行时间。这意味着在我们的列表推导式完成其表达式后,我们将在内存中拥有两个列表。但是,filter()
将创建一个简单的对象,该对象包含对原始列表的引用、提供的函数以及原始列表中的位置的索引,这将占用较少的内存。
在本教程中,我们将回顾四种不同的使用方式filter()
:使用两种不同的可迭代结构、使用lambda
函数和未定义函数。
使用filter()
与功能
的第一个参数filter()
是一个函数,我们用它来决定是包含还是过滤掉每个项目。该函数为作为第二个参数传递的迭代中的每个项目调用一次,每次返回时False
,该值都会被删除。由于这个参数是一个函数,我们可以传递一个普通函数,也可以使用lambda
函数,特别是当表达式不太复杂时。
以下是lambda
with的语法filter()
:
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'
。
最后我们传递了 iterable 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
定义了我们将实现的表达式 filter 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()
函数 withNone
并传入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
或者我们可以用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()
as 函数传递给filter()
. 该filter_set()
函数将返回由 产生的迭代器filter()
。
在iterator_func()
需要x
作为一个参数,它代表了我们的列表中的项目(即单字典)。
接下来,for
循环访问字典中每个键:值对中的值,然后使用条件语句检查 是否在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
已经返回。使用我们自己的嵌套函数允许我们访问每个项目并根据搜索字符串有效地检查每个项目。
结论
在本教程中,我们学习了filter()
在 Python中使用该函数的不同方式。现在,您可以使用filter()
自己的函数、lambda
函数或 withNone
来过滤具有不同复杂性数据结构的项目。
尽管在本教程中我们filter()
以列表格式立即打印结果,但在我们的程序中我们很可能会使用返回的filter()
对象并进一步操作数据。
如果您想了解更多 Python,请查看我们的How To Code in Python 3系列和我们的Python 主题页面。