Python函数:filter()函数按条件过滤序列元素
Python函数filter()函数按条件过滤序列元素一、开篇从序列中筛选出你需要的数据处理中过滤是最基本的操作之一从一堆数据中选出符合条件的。Python的filter()函数就是专门干这个的——它像一个筛子只让满足条件的元素通过。⌨️ 先看一个简单例子# 从1-10中筛选出偶数numbers[1,2,3,4,5,6,7,8,9,10]# 方法一for循环evens1[]forninnumbers:ifn%20:evens1.append(n)# 方法二列表推导式evens2[nforninnumbersifn%20]# 方法三filter()函数evens3list(filter(lambdan:n%20,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):判断是否为正数returnn0numbers[-3,-1,0,2,5,-4,7]positiveslist(filter(is_positive,numbers))print(positives)# [2, 5, 7]# 使用lambdapositives2list(filter(lambdan:n0,numbers))print(positives2)# [2, 5, 7]# ⚠️ filter对象是迭代器——只能遍历一次resultfilter(is_positive,numbers)print(list(result))# [2, 5, 7]print(list(result))# [] 迭代器已耗尽2.2 function为None的特殊行为# 当functionNone时filter()会过滤掉所有假值元素# 假值False, None, 0, 0.0, , [], {}, (), set()items[0,1,,hello,None,[],[1,2],False,True,{},{a:1}]truthylist(filter(None,items))print(truthy)# [1, hello, [1, 2], True, {a: 1}]# 实际应用过滤掉空字符串words[python,,java, ,rust,,go]# filter(None) 不会过滤 空白字符也是非空字符串non_emptylist(filter(None,words))print(non_empty)# [python, java, , rust, go]# 如果要过滤纯空格字符串non_blanklist(filter(lambdas:s.strip(),words))print(non_blank)# [python, java, rust, go]# 实际场景清理用户输入中的无效选项user_inputs[选项A,,None,选项B, ,选项C]valid_inputslist(filter(lambdax:xandx.strip(),user_inputs))print(valid_inputs)# [选项A, 选项B, 选项C]2.3 filter()配合内置方法和函数# 使用str的方法作为过滤条件words[Python,java,Rust,GO,typescript,C]# 筛选全小写的lowercase_wordslist(filter(str.islower,words))print(lowercase_words)# [java, typescript]# 筛选全大写的uppercase_wordslist(filter(str.isupper,words))print(uppercase_words)# [GO]# 筛选以特定字符开头的starts_with_plist(filter(lambdas:s.lower().startswith(p),words))print(starts_with_p)# [Python]# 筛选数字mixed[abc,123,hello456,789,word]is_digitlist(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且活跃qualifiedlist(filter(lambdau:u[age]20andu[score]80andu[active],data))print([u[name]foruinqualified])# [张三, 李四]# 多个条件OR关系年龄大于30或分数大于90speciallist(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_userslist(filter(is_qualified,data))excellent_userslist(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_scorersfilter(lambdas:s[math]s[english]160,students)formattedmap(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)# 相同结果# 列表推导式在处理filtermap组合时通常更简洁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# 链式过滤step1filter(filter_genre(科幻),movies)step2filter(filter_min_rating(9.0),step1)step3filter(filter_after_year(2010),step2)resultlist(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: 保留偶数evenslist(filter(lambdax:x%20,numbers))print(evens)# [0, 2, 4, 6, 8]# filterfalse: 排除偶数即保留奇数oddslist(filterfalse(lambdax:x%20,numbers))print(odds)# [1, 3, 5, 7, 9]# 实际应用过滤掉无效数据data[valid1,,valid2,None,valid3, ]# 排除空值和Nonedefis_invalid(value):returnvalueisNoneor(isinstance(value,str)andnotvalue.strip())valid_datalist(filterfalse(is_invalid,data))print(valid_data)# [valid1, valid2, valid3]五、实战案例5.1 数据清洗# 场景清洗从CSV读取的数据raw_data[[张三,25,zhangsanemail.com,北京],[李四,,lisiemail.com,上海],# 年龄缺失[,30,wangwuemail.com,广州],# 姓名缺失[赵六,28,,深圳],# 邮箱缺失[钱七,35,qianqiemail.com,],# 城市缺失[孙八,invalid,sunbaemail.com,杭州],# 年龄无效]defis_valid_row(row):检查数据行是否完整有效name,age_str,email,cityrow# 检查非空ifnotall([name,age_str,email,city]):returnFalse# 检查年龄是数字try:ageint(age_str)ifage0orage150:returnFalseexceptValueError:returnFalse# 检查邮箱包含ifnotinemail:returnFalsereturnTrue# 过滤并转换valid_datafilter(is_valid_row,raw_data)cleanedlist(map(lambdarow:{name:row[0],age:int(row[1]),email:row[2],city:row[3],},valid_data))forrecordincleaned:print(record)# {name: 张三, age: 25, email: zhangsanemail.com, city: 北京}5.2 用户输入校验# 场景批量验证用户提交的注册信息registrations[{username:alice,email:alicetest.com,age:25,password:abc12345},{username:bob,email:bob,age:30,password:12345678},# 邮箱格式不对{username:charlie,email:charlietest.com,age:17,password:pw},# 年龄和密码不符合{username:d,email:dianatest.com,age:22,password:pass123},# 用户名太短]defvalidate_registration(reg):验证注册信息errors[]iflen(reg[username])3:errors.append(用户名至少3个字符)ifnotinreg[email]or.notinreg[email]:errors.append(邮箱格式不正确)ifreg[age]18:errors.append(年龄必须≥18岁)iflen(reg[password])8:errors.append(密码至少8个字符)returnlen(errors)0,errors# 筛选出验证失败的invalidlist(filterfalse(lambdar:validate_registration(r)[0],registrations))forrininvalid:_,errorsvalidate_registration(r)print(f{r[username]}:{, .join(errors)})# bob: 邮箱格式不正确# charlie: 年龄必须≥18岁, 密码至少8个字符# d: 用户名至少3个字符六、总结filter()是Python数据处理的必备工具。它和map()、lambda一起构成了Python函数式编程的基础三件套。核心要点filter(func, iterable)返回满足条件的元素组成的迭代器filter(None, iterable)过滤掉假值0、“”、None、[]等filterfalse(func, iterable)是filter的反向版本有复杂条件时用命名的过滤函数代替lambda更清晰filtermap组合很适合做数据处理流水线✅选型建议filtermap的组合 → 列表推导式通常更简洁使用内置函数作为过滤条件 →filter(str.isdigit, data)很优雅链式多层过滤 → 考虑用filterfalse排除法思路大型数据集 → filter的惰性求值可以节省内存