首页 > temp > python入门教程 >
-
1.16 过滤序列元素
问题描述
你有一个数据序列,想利用一些规则从中提取出需要的值或是缩短的序列。
解决方案
最简答的过滤序列元素的方法就是使用列表推导式。比如:
mylist = [1, 4, -5, 10, -7, 2, 3, -1]
res = [n for n in mylist if n > 0]
"""
res = [1, 4, 10, 2, 3]
"""
如果你对内存比较敏感,可以使用生成器表达式迭代产生过滤的元素。比如:
gen = (n for n in mylist if n > 0)
print(gen)
""" 输出结果:
<generator object <genexpr> at 0x000001E4C8796CF0>
"""
for i in gen:
print(i)
""" 输出结果:
1
4
10
2
3
"""
有时候过滤规则比较复杂,不能简单的在列表推导式或者生成器表达式中表达出来。比如,过滤的时候需要处理一些异常或其他复杂情况。这时候你可以将过滤代码封装到一个函数中,然后使用内置函数filter()
。例如:
values = ['1', '2', '-3', '-', '4', 'N/A', '5']
def is_int(v):
try:
x = int(v)
return True
except ValueError:
return False
res = list(filter(is_int, values))
print(res)
"""输出结果:
['1', '2', '-3', '4', '5']
"""
需要注意,filter()
函数创建的是一个迭代器。
讨论
由官方文档的介绍,列表推导式的方括号内包含以下内容:一个表达式,后面为一个for子句,然后是零个或多个for或if子句。结果是由表达式依据for和if子句求值计算而得出一个新列表。清楚了概念,再看下面几个例子。
列表推导式和生成器表达式通常是过滤数据最简单的方式。它们还能在过滤的时候转换数据。例如:
import math
mylist = [1, 4, -5, 10, -7, 2, 3, -1]
res = [math.sqrt(n) for n in mylist if n > 0]
print(res)
"""输出结果:
[1.0, 2.0, 3.1622776601683795, 1.4142135623730951, 1.7320508075688772]
"""
过滤操作的一个变种是将不符合条件的值用新的值替代,而不是丢掉它们。比如,你不仅想找到正数,还想将不是正数的数换成0。通过将过滤条件放到条件表达式中,就可以很容易地解决这个问题:
res = [n if n > 0 else 0 for n in mylist]
"""
res = [1, 4, 0, 10, 0, 2, 3, 0]
"""
res = [n if n < 0 else 0 for n in mylist]
"""
res = [0, 0, -5, 0, -7, 0, 0, -1]
"""
另外一个值得关注的过滤工具就是itertools.compress()
,它以一个iterable
对象和一个相对应的Boolean
选择器序列作为输入参数。然后输出iterable
对象中对应选择器为True
的元素。当你需要用另一个相关联的序列来过滤某个序列的时候,这个函数是非常有用的。例如,你有如下两组数据:
addresses = [
'5412 N CLARK',
'5148 N CLARK',
'5800 E 58TH',
'2122 N CLARK',
'5645 N RAVENSWOOD',
'1060 W ADDISON',
'4801 N BROADWAY',
'1039 W GRANVILLE',
]
counts = [ 0, 3, 10, 4, 1, 7, 6, 1]
这两个序列的元素个数是相等的,也就是它们的元素可以是一一对应的关系。现在你想将对应count值大于5的地址值全部输出,那么你可以:
for itertools import compress
more5 = [n > 5 for n in counts]
print(more5)
"""输出结果:
[False, False, True, False, False, True, True, False]
"""
res = list(compress(addresses, more5))
print(res)
"""输出结果:
['5800 E 58TH', '1060 W ADDISON', '4801 N BROADWAY']
"""
这里的关键点在于先创建一个Boolean
序列,指示哪些元素符合条件。然后compress()
函数根据这个序列去选择输出对应位置为True
的元素。
和filter()
函数类似,compress()
返回的也是一个迭代器。因此,如果你想得到一个列表,那么你需要使用list()
来将结果转换为列表类型。
总结
本节介绍了过滤序列元素的几种方法。
最简单的方法就是利用列表推导式,如果你对内存使用有要求,可以改用生成器表达式。如果过滤规则过于复杂,无法在列表推导式或生成器表达式中表达出来,可以使用内置函数filter()
。
另外还介绍了一个过滤工具itertools.compress()
,当你需要通过另一个相关联的序列来过滤某个序列时,可以用到它。
原文:https://www.cnblogs.com/L999C/p/15749290.html