目录
- 问题
- 解决方案
- 讨论
问题
序列中包含一些数据,我们需要提取出其中的值或根据某些标准对序列做删减。
解决方案
要筛选序列中的元素,通常最简单的办法是通过 列表推导式,例如:
mylist = [1, 4, -5, 10, -7, 2, 3, -1]print([n for n in mylist if n > 0])
print([m for m in mylist if m <= 0])
但是列表推导式存在着一些缺点,比如相对可读性差,比如其会一次性生成整个列表,在生成非常大的列表时,会导致消耗大量内存。
相比之下,生成器表达式 可以更加有效地使用内存,因为其会逐个产生元素而不是一次性生成整个列表。
pos = (n for n in mylist if n > 0)
print(pos)
for x in pos:print(x)
有时候,如果筛选条件过于复杂,就不宜使用列表推导式以及生成器表达式。这时,我们可以选择将筛选逻辑代码放在单独的函数中,然后使用内建的 filter()
函数处理。
values = ['1', '2', '-3', '-', '4', 'N/A', '5']def is_int(val):try:x = int(val)return Trueexcept ValueError:return Falseisvals = list(filter(is_int, values))
print(isvals)
filter()
创建了一个迭代器,而我们想要筛选得到列表中所有整数,且以列表的形式展示,所以加上 list()
。
讨论
列表推导式以及生成器表达式通常是用来筛选数据的最简单和最直接的方式。其功能强大,具备同时对数据进行转换的能力:
mylist = [1, 4, -5, 10, -7, 2, 3, -1]import math
print([math.sqrt(n) for n in mylist if n > 0])
此外,列表推导式以及生成器表达式也可以实现同时对不满足条件的字段做标注,比如标注出不满足 >=0
的条件的值,其余值取平方根:
mylist = [1, 4, -5, 16, -7, -9, 25, 36]import math
print([math.sqrt(n) if n > 0 else -1 for n in mylist])
结果:
[1.0, 2.0, -1, 4.0, -1, -1, 5.0, 6.0]
此外,除了列表推导式以及生成器表达式,python 还提供一种筛选工具:itertools.compress()
,其接受一个可迭代对象以及一个布尔选择器序列作为输入。输出时,会给出所有在相应的布尔选择器中为 True
的可迭代对象元素。
address = ['5412 N CLARK','5149 N CLARK','5800 E 58TH','2122 N CLARK','5645 N RAVESWOOD','1060 W ADDISON','4901 N BROADWAY','1039 W GRANVILLE'
]counts = [0, 3, 10, 4, 1, 7, 6, 1]from itertools import compress
more5 = [n > 5 for n in counts]
print(list(compress(address, more5)))
['5800 E 58TH', '1060 W ADDISON', '4901 N BROADWAY']
同 filter()
函数一样,compress()
同样会返回一个迭代器,我们需要通过 list()
将其结果转换为列表。