news 2026/7/19 12:20:55

Python函数:filter()函数按条件过滤序列元素

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Python函数:filter()函数按条件过滤序列元素

Python函数:filter()函数按条件过滤序列元素

一、开篇:从序列中"筛选"出你需要的

数据处理中,过滤是最基本的操作之一:从一堆数据中选出符合条件的。Python的filter()函数就是专门干这个的——它像一个筛子,只让满足条件的元素通过。

⌨️ 先看一个简单例子:

# 从1-10中筛选出偶数numbers=[1,2,3,4,5,6,7,8,9,10]# 方法一:for循环evens1=[]forninnumbers:ifn%2==0:evens1.append(n)# 方法二:列表推导式evens2=[nforninnumbersifn%2==0]# 方法三:filter()函数evens3=list(filter(lambdan:n%2==0,numbers))print(evens1)# [2, 4, 6, 8, 10]print(evens2)# [2, 4, 6, 8, 10]print(evens3)# [2, 4, 6, 8, 10]

💡filter()map()一样,返回的是迭代器(惰性求值)。它的核心优势在于可以很方便地与map()、其他迭代器组合,构建数据处理流水线。

二、filter()的基本用法

2.1 语法和核心概念

# filter()的语法# filter(function, iterable)# function: 过滤函数,返回True保留元素,返回False丢弃元素# iterable: 可迭代对象# 返回值: filter对象(迭代器)# 基本示例defis_positive(n):"""判断是否为正数"""returnn>0numbers=[-3,-1,0,2,5,-4,7]positives=list(filter(is_positive,numbers))print(positives)# [2, 5, 7]# 使用lambdapositives2=list(filter(lambdan:n>0,numbers))print(positives2)# [2, 5, 7]# ⚠️ filter对象是迭代器——只能遍历一次result=filter(is_positive,numbers)print(list(result))# [2, 5, 7]print(list(result))# [] 迭代器已耗尽

2.2 function为None的特殊行为

# 💡 当function=None时,filter()会过滤掉所有"假值"元素# 假值:False, None, 0, 0.0, "", [], {}, (), set()items=[0,1,"","hello",None,[],[1,2],False,True,{},{"a":1}]truthy=list(filter(None,items))print(truthy)# [1, 'hello', [1, 2], True, {'a': 1}]# 实际应用:过滤掉空字符串words=["python","","java"," ","rust","","go"]# filter(None) 不会过滤 " "(空白字符也是非空字符串)non_empty=list(filter(None,words))print(non_empty)# ['python', 'java', ' ', 'rust', 'go']# 如果要过滤纯空格字符串non_blank=list(filter(lambdas:s.strip(),words))print(non_blank)# ['python', 'java', 'rust', 'go']# 💡 实际场景:清理用户输入中的无效选项user_inputs=["选项A","",None,"选项B"," ","选项C"]valid_inputs=list(filter(lambdax:xandx.strip(),user_inputs))print(valid_inputs)# ['选项A', '选项B', '选项C']

2.3 filter()配合内置方法和函数

# 使用str的方法作为过滤条件words=["Python","java","Rust","GO","typescript","C"]# 筛选全小写的lowercase_words=list(filter(str.islower,words))print(lowercase_words)# ['java', 'typescript']# 筛选全大写的uppercase_words=list(filter(str.isupper,words))print(uppercase_words)# ['GO']# 筛选以特定字符开头的starts_with_p=list(filter(lambdas:s.lower().startswith("p"),words))print(starts_with_p)# ['Python']# 筛选数字mixed=["abc","123","hello456","789","word"]is_digit=list(filter(str.isdigit,mixed))print(is_digit)# ['123', '789']

三、filter()的进阶用法

3.1 多个条件组合

data=[{"name":"张三","age":28,"score":85,"active":True},{"name":"李四","age":22,"score":92,"active":True},{"name":"王五","age":35,"score":78,"active":False},{"name":"赵六","age":19,"score":95,"active":True},{"name":"钱七","age":30,"score":65,"active":True},]# 多个条件(AND关系):年龄大于20且分数大于80且活跃qualified=list(filter(lambdau:u["age"]>20andu["score"]>80andu["active"],data))print([u["name"]foruinqualified])# ['张三', '李四']# 多个条件(OR关系):年龄大于30或分数大于90special=list(filter(lambdau:u["age"]>30oru["score"]>90,data))print([u["name"]foruinspecial])# ['李四', '王五', '赵六']# 条件函数分离——提高可读性defis_qualified(user):"""判断用户是否合格"""return(user["age"]>=20anduser["score"]>=60anduser["active"])defis_excellent(user):"""判断用户是否优秀"""returnuser["score"]>=90qualified_users=list(filter(is_qualified,data))excellent_users=list(filter(is_excellent,qualified_users))print([u["name"]foruinexcellent_users])# ['李四', '赵六']

3.2 filter()与map()的组合

# 💡 经典模式:先过滤(filter),再转换(map)# 场景:从学生列表中筛选出高分学生,并格式化输出students=[{"name":"Alice","math":85,"english":92},{"name":"Bob","math":65,"english":70},{"name":"Charlie","math":95,"english":88},{"name":"Diana","math":72,"english":90},{"name":"Eve","math":58,"english":62},]# 流水线:筛选(总分>160) → 计算总分 → 格式化# 方法一:filter + maphigh_scorers=filter(lambdas:s["math"]+s["english"]>160,students)formatted=map(lambdas:f"{s['name']}:{s['math']+s['english']}分",high_scorers)print(list(formatted))# ['Alice: 177分', 'Charlie: 183分', 'Diana: 162分']# 方法二:列表推导式(一条龙)result=[f"{s['name']}:{s['math']+s['english']}分"forsinstudentsifs["math"]+s["english"]>160]print(result)# 相同结果# 💡 列表推导式在处理filter+map组合时通常更简洁

3.3 链式过滤

# 应用多个过滤条件,逐步筛选# 场景:电影推荐系统movies=[{"title":"盗梦空间","genre":"科幻","rating":9.3,"year":2010},{"title":"肖申克的救赎","genre":"剧情","rating":9.7,"year":1994},{"title":"星际穿越","genre":"科幻","rating":9.4,"year":2014},{"title":"霸王别姬","genre":"剧情","rating":9.6,"year":1993},{"title":"阿凡达","genre":"科幻","rating":8.7,"year":2009},{"title":"泰坦尼克号","genre":"爱情","rating":9.4,"year":1997},{"title":"流浪地球","genre":"科幻","rating":7.9,"year":2019},]# 筛选条件:科幻片 + 评分>=9.0 + 2010年之后deffilter_genre(genre):returnlambdamovie:movie["genre"]==genredeffilter_min_rating(rating):returnlambdamovie:movie["rating"]>=ratingdeffilter_after_year(year):returnlambdamovie:movie["year"]>=year# 链式过滤step1=filter(filter_genre("科幻"),movies)step2=filter(filter_min_rating(9.0),step1)step3=filter(filter_after_year(2010),step2)result=list(step3)formovieinresult:print(f"{movie['title']}({movie['year']}) -{movie['rating']}分")# 星际穿越 (2014) - 9.4分# 💡 或者用列表推导式一行搞定result2=[mforminmoviesifm["genre"]=="科幻"andm["rating"]>=9.0andm["year"]>=2010]

四、itertools.filterfalse()

# filterfalse():与filter()相反——保留函数返回False的元素fromitertoolsimportfilterfalse numbers=[0,1,2,3,4,5,6,7,8,9]# filter: 保留偶数evens=list(filter(lambdax:x%2==0,numbers))print(evens)# [0, 2, 4, 6, 8]# filterfalse: 排除偶数(即保留奇数)odds=list(filterfalse(lambdax:x%2==0,numbers))print(odds)# [1, 3, 5, 7, 9]# 实际应用:过滤掉无效数据data=["valid1","","valid2",None,"valid3"," "]# 排除空值和Nonedefis_invalid(value):returnvalueisNoneor(isinstance(value,str)andnotvalue.strip())valid_data=list(filterfalse(is_invalid,data))print(valid_data)# ['valid1', 'valid2', 'valid3']

五、实战案例

5.1 数据清洗

# 场景:清洗从CSV读取的数据raw_data=[["张三","25","zhangsan@email.com","北京"],["李四","","lisi@email.com","上海"],# 年龄缺失["","30","wangwu@email.com","广州"],# 姓名缺失["赵六","28","","深圳"],# 邮箱缺失["钱七","35","qianqi@email.com",""],# 城市缺失["孙八","invalid","sunba@email.com","杭州"],# 年龄无效]defis_valid_row(row):"""检查数据行是否完整有效"""name,age_str,email,city=row# 检查非空ifnotall([name,age_str,email,city]):returnFalse# 检查年龄是数字try:age=int(age_str)ifage<=0orage>150:returnFalseexceptValueError:returnFalse# 检查邮箱包含@if"@"notinemail:returnFalsereturnTrue# 过滤并转换valid_data=filter(is_valid_row,raw_data)cleaned=list(map(lambdarow:{"name":row[0],"age":int(row[1]),"email":row[2],"city":row[3],},valid_data))forrecordincleaned:print(record)# {'name': '张三', 'age': 25, 'email': 'zhangsan@email.com', 'city': '北京'}

5.2 用户输入校验

# 场景:批量验证用户提交的注册信息registrations=[{"username":"alice","email":"alice@test.com","age":25,"password":"abc12345"},{"username":"bob","email":"bob","age":30,"password":"12345678"},# 邮箱格式不对{"username":"charlie","email":"charlie@test.com","age":17,"password":"pw"},# 年龄和密码不符合{"username":"d","email":"diana@test.com","age":22,"password":"pass123"},# 用户名太短]defvalidate_registration(reg):"""验证注册信息"""errors=[]iflen(reg["username"])<3:errors.append("用户名至少3个字符")if"@"notinreg["email"]or"."notinreg["email"]:errors.append("邮箱格式不正确")ifreg["age"]<18:errors.append("年龄必须≥18岁")iflen(reg["password"])<8:errors.append("密码至少8个字符")returnlen(errors)==0,errors# 筛选出验证失败的invalid=list(filterfalse(lambdar:validate_registration(r)[0],registrations))forrininvalid:_,errors=validate_registration(r)print(f"{r['username']}:{', '.join(errors)}")# bob: 邮箱格式不正确# charlie: 年龄必须≥18岁, 密码至少8个字符# d: 用户名至少3个字符

六、总结

filter()是Python数据处理的必备工具。它和map()lambda一起,构成了Python函数式编程的基础三件套。

💡核心要点:

  1. filter(func, iterable)返回满足条件的元素组成的迭代器
  2. filter(None, iterable)过滤掉假值(0、“”、None、[]等)
  3. filterfalse(func, iterable)是filter的"反向"版本
  4. 有复杂条件时,用命名的过滤函数代替lambda更清晰
  5. filter+map组合很适合做数据处理流水线

选型建议:

  • filter+map的组合 → 列表推导式通常更简洁
  • 使用内置函数作为过滤条件 →filter(str.isdigit, data)很优雅
  • 链式多层过滤 → 考虑用filterfalse排除法思路
  • 大型数据集 → filter的惰性求值可以节省内存
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/19 12:20:30

OpenBoardView终极指南:免费开源PCB查看器快速上手教程

OpenBoardView终极指南&#xff1a;免费开源PCB查看器快速上手教程 【免费下载链接】OpenBoardView View .brd files 项目地址: https://gitcode.com/gh_mirrors/op/OpenBoardView 还在为无法打开.brd文件而烦恼吗&#xff1f;作为一名硬件工程师或电子爱好者&#xff0…

作者头像 李华
网站建设 2026/7/19 12:19:06

G-Helper:华硕笔记本终极性能优化指南,让你的设备重获新生

G-Helper&#xff1a;华硕笔记本终极性能优化指南&#xff0c;让你的设备重获新生 【免费下载链接】g-helper Lightweight Armoury Crate alternative for Asus laptops with nearly the same functionality. Works with ROG Zephyrus, Flow, TUF, Strix, Scar, ProArt, Vivobo…

作者头像 李华
网站建设 2026/7/19 12:18:18

【实战指南】ODrive开源电机控制器:从零搭建高性能运动控制系统

【实战指南】ODrive开源电机控制器&#xff1a;从零搭建高性能运动控制系统 【免费下载链接】ODrive High performance motor control 项目地址: https://gitcode.com/gh_mirrors/od/ODrive 你是否曾经遇到过这样的困扰&#xff1a;想要为机器人关节、CNC机床或者自动化…

作者头像 李华
网站建设 2026/7/19 12:17:56

AM261x外设集成深度解析:从时钟、总线到多核协同的嵌入式开发实践

1. 项目概述与核心价值在嵌入式开发领域&#xff0c;尤其是基于德州仪器&#xff08;TI&#xff09;Sitara系列高性能微控制器的项目中&#xff0c;深入理解芯片内部的外设集成架构&#xff0c;是打通从硬件原理图到稳定可靠软件驱动之间“最后一公里”的关键。很多工程师在项目…

作者头像 李华
网站建设 2026/7/19 12:16:15

3步搞定Harvester超融合平台网络配置:VIP、VLAN与多网卡实战指南

3步搞定Harvester超融合平台网络配置&#xff1a;VIP、VLAN与多网卡实战指南 【免费下载链接】harvester Open source hyperconverged infrastructure (HCI) software 项目地址: https://gitcode.com/gh_mirrors/ha/harvester 想要快速部署一个稳定高效的Kubernetes超融…

作者头像 李华
网站建设 2026/7/19 12:15:31

AMD 7840HS核显在ESXi中的直通配置与性能优化

1. 项目背景与核心需求 在虚拟化环境中实现GPU直通一直是个热门话题&#xff0c;尤其是对于AMD 7840HS这类集成显卡的直通需求。7840HS作为AMD锐龙7000系列移动处理器中的中高端型号&#xff0c;其RDNA3架构的Radeon 780M核显性能接近入门级独显&#xff0c;在ESXi虚拟化环境中…

作者头像 李华