欢迎光临
我们一直在努力

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

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

在这里插入图片描述

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

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

⌨️ 先看一个简单例子:

# 从1-10中筛选出偶数
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

# 方法一:for循环
evens1 = []
for n in numbers:
if n % 2 == 0:
evens1.append(n)

# 方法二:列表推导式
evens2 = [n for n in numbers if n % 2 == 0]

# 方法三:filter()函数
evens3 = list(filter(lambda n: 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对象(迭代器)

# 基本示例
def is_positive(n):
"""判断是否为正数"""
return n > 0

numbers = [3, 1, 0, 2, 5, 4, 7]
positives = list(filter(is_positive, numbers))
print(positives) # [2, 5, 7]

# 使用lambda
positives2 = list(filter(lambda n: 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(lambda s: s.strip(), words))
print(non_blank) # ['python', 'java', 'rust', 'go']

# 💡 实际场景:清理用户输入中的无效选项
user_inputs = ["选项A", "", None, "选项B", " ", "选项C"]
valid_inputs = list(filter(lambda x: x and x.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(lambda s: 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(
lambda u: u["age"] > 20 and u["score"] > 80 and u["active"],
data
))
print([u["name"] for u in qualified]) # ['张三', '李四']

# 多个条件(OR关系):年龄大于30或分数大于90
special = list(filter(
lambda u: u["age"] > 30 or u["score"] > 90,
data
))
print([u["name"] for u in special]) # ['李四', '王五', '赵六']

# 条件函数分离——提高可读性
def is_qualified(user):
"""判断用户是否合格"""
return (
user["age"] >= 20
and user["score"] >= 60
and user["active"]
)

def is_excellent(user):
"""判断用户是否优秀"""
return user["score"] >= 90

qualified_users = list(filter(is_qualified, data))
excellent_users = list(filter(is_excellent, qualified_users))
print([u["name"] for u in excellent_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 + map
high_scorers = filter(lambda s: s["math"] + s["english"] > 160, students)
formatted = map(
lambda s: 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']}分"
for s in students
if s["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年之后
def filter_genre(genre):
return lambda movie: movie["genre"] == genre

def filter_min_rating(rating):
return lambda movie: movie["rating"] >= rating

def filter_after_year(year):
return lambda movie: 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)

for movie in result:
print(f" {movie['title']} ({movie['year']}) – {movie['rating']}分")
# 星际穿越 (2014) – 9.4分

# 💡 或者用列表推导式一行搞定
result2 = [
m for m in movies
if m["genre"] == "科幻" and m["rating"] >= 9.0 and m["year"] >= 2010
]

四、itertools.filterfalse()

# filterfalse():与filter()相反——保留函数返回False的元素
from itertools import filterfalse

numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# filter: 保留偶数
evens = list(filter(lambda x: x % 2 == 0, numbers))
print(evens) # [0, 2, 4, 6, 8]

# filterfalse: 排除偶数(即保留奇数)
odds = list(filterfalse(lambda x: x % 2 == 0, numbers))
print(odds) # [1, 3, 5, 7, 9]

# 实际应用:过滤掉无效数据
data = ["valid1", "", "valid2", None, "valid3", " "]
# 排除空值和None
def is_invalid(value):
return value is None or (isinstance(value, str) and not value.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", "杭州"], # 年龄无效
]

def is_valid_row(row):
"""检查数据行是否完整有效"""
name, age_str, email, city = row
# 检查非空
if not all([name, age_str, email, city]):
return False
# 检查年龄是数字
try:
age = int(age_str)
if age <= 0 or age > 150:
return False
except ValueError:
return False
# 检查邮箱包含@
if "@" not in email:
return False
return True

# 过滤并转换
valid_data = filter(is_valid_row, raw_data)
cleaned = list(map(
lambda row: {
"name": row[0],
"age": int(row[1]),
"email": row[2],
"city": row[3],
},
valid_data
))

for record in cleaned:
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"}, # 用户名太短
]

def validate_registration(reg):
"""验证注册信息"""
errors = []

if len(reg["username"]) < 3:
errors.append("用户名至少3个字符")
if "@" not in reg["email"] or "." not in reg["email"]:
errors.append("邮箱格式不正确")
if reg["age"] < 18:
errors.append("年龄必须≥18岁")
if len(reg["password"]) < 8:
errors.append("密码至少8个字符")

return len(errors) == 0, errors

# 筛选出验证失败的
invalid = list(filterfalse(lambda r: validate_registration(r)[0], registrations))
for r in invalid:
_, errors = validate_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更清晰
  • filter+map组合很适合做数据处理流水线
  • ✅ 选型建议:

    • filter+map的组合 → 列表推导式通常更简洁
    • 使用内置函数作为过滤条件 → filter(str.isdigit, data)很优雅
    • 链式多层过滤 → 考虑用filterfalse排除法思路
    • 大型数据集 → filter的惰性求值可以节省内存
    赞(0)
    未经允许不得转载:171主机测评 » Python函数:filter()函数按条件过滤序列元素
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址