最常用方式是array_filter(),需正确编写回调函数并返回布尔值;按键名筛选应使用array_keys()+array_intersect_key();筛选后需用array_values()重置索引。

用 array_filter() 筛选含指定值的元素
最常用也最灵活的方式是 array_filter(),它不修改原数组,返回新数组。关键点在于回调函数怎么写——别直接用 == 比较整个元素,要明确比哪一维。
比如筛选关联数组中 status 为 "active" 的项:
filter(function ($item) {
return $item['status'] === 'active';
}, $users);
常见错误:漏掉 return,或用 = 赋值代替比较;还有人传字符串进去当回调,结果报 Warning: array_filter() expects parameter 2 to be a valid callback。
- 回调必须返回布尔值,
true表示保留,false被过滤 - 如果数组键名重要,加第三个参数
ARRAY_FILTER_USE_BOTH,就能在回调里拿到键 - PHP 7.4+ 支持箭头函数,可简写为
array_filter($arr, fn($x) => $x['id'] > 10)
按键名筛选用 array_keys() + array_intersect_key()
当你想“找出所有键名等于 "name"、"email" 的字段”,不是按值找,而是按键找——这时候别硬套 array_filter(),效率低还绕。
立即学习“PHP免费学习笔记(深入)”;
正确做法分两步:array_keys() 先提取所有键,再用 array_intersect_key() 对齐保留:
$allowed = ['name', 'email', 'phone']; $result = array_intersect_key($user, array_flip($allowed));
注意 array_flip() 是必须的,因为 array_intersect_key() 比较的是键,不是值;如果 $user 里没有某个键(比如没 "phone"),结果里也不会有,不会报错也不会补 null。
筛选后重置索引用 array_values()
array_filter() 保留原始键名,数字索引可能变成 [2] => ..., [5] => ...,后续用 for 循环或 array_shift() 就会出问题。
需要连续数字索引时,必须显式调用:
$filtered = array_values(array_filter($arr, $callback));
这个步骤经常被跳过,导致后续 foreach 没问题,但一上 for ($i = 0; $i 就漏数据——因为 count() 返回的是元素个数,但索引不连续,$filtered[1] 可能根本不存在。
大数据量时慎用 in_array() 做多值匹配
想筛选出 type 是 "admin" 或 "editor" 或 "moderator" 的记录?别这么写:
array_filter($users, function($u) {
return in_array($u['type'], ['admin', 'editor', 'moderator']);
});
看起来简洁,但每次循环都执行一次 in_array(),内部是线性扫描。如果白名单数组变长,或 $users 有几千条,性能明显下滑。
更优解是先转成 array_flip() 建哈希表:
$whitelist = array_flip(['admin', 'editor', 'moderator']);
array_filter($users, function($u) use ($whitelist) {
return isset($whitelist[$u['type']]);
});
这样每次判断是 O(1)。别小看这点——线上接口从 120ms 掉到 35ms,往往就差这一行。
键名是否区分大小写、空格、null 值处理,这些细节在真实业务数据里几乎必踩,得在回调里提前 trim()、strtolower() 或判空。










