VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > 编程开发 > 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


相关教程