PHP中array_filter()结合字符串函数筛选人名失效的解决办法
问题描述
有一组包含人名与年龄的人员列表,使用array_filter()能正确筛选出年龄超过40岁的人员,但用strpos()筛选名字包含指定字符串(如"sapi")的人员时,无法得到预期结果(本该匹配"sapi"和"rahmatsapi"),尝试strpbrk()等函数也未成功。相关代码如下:
$listL = [ ['name' => 'sapi', 'age' => 49], ['name' => 'rahmatsapi', 'age' => 42], ['name' => 'neko', 'age' => 39] ]; $filterUser = array_filter($listL, fn($user) => $user['age'] > 40); $filterUser = array_filter($listL, fn($user) => strpos($user['name'], 'sapi')); var_dump($filterUser);
需解决:
- 若必须使用
array_filter()函数与字符串函数,正确的实现方式是什么? - 若字符串函数不具备该能力,替代方案是什么?
解决方案
一、array_filter()+字符串函数的正确实现
问题根源是strpos()的返回值逻辑:当目标子串在字符串开头时,strpos()返回0,而array_filter()会把0判定为false过滤掉,导致"sapi"被错误排除。
正确写法是严格判断返回值不等于false(只有子串不存在时strpos()才返回false):
$filterUser = array_filter($listL, fn($user) => strpos($user['name'], 'sapi') !== false);
至于strpbrk(),它的作用是匹配任意单个指定字符,并不适合子串匹配场景,所以不推荐用它处理这类需求。
二、替代方案
如果不想用strpos(),可以选择以下两种更直观的方式:
str_contains()(PHP 8.0+):PHP8新增的专门判断子串是否存在的函数,语义清晰,无需处理返回值的边界问题:
$filterUser = array_filter($listL, fn($user) => str_contains($user['name'], 'sapi'));
- 正则表达式
preg_match():适合复杂匹配场景(比如大小写不敏感、多规则匹配),基础子串匹配写法如下:
$filterUser = array_filter($listL, fn($user) => preg_match('/sapi/', $user['name']) === 1);
内容的提问来源于stack exchange,提问作者arseni44
相关产品推荐
相关产品推荐

