登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  文章 >  php教程

PHP array_filter 怎样保留键并处理零值

来源:17golang原创

时间:2026-10-26 03:30:21 367浏览 收藏

用 array_filter() 筛数组时,最容易踩到两个坑:它默认保留原键;不传回调时又会按 empty() 的语义删除值。因此,想“保留 0”不能直接写无回调版本,而要把业务规则写进回调。需要得到连续 JSON 列表时,再额外调用 array_values()。

结论:保留关联键用带回调的 array_filter($items, $callback);保留整数 0 时使用严格比较;按键筛选传 ARRAY_FILTER_USE_KEY,同时判断键和值传 ARRAY_FILTER_USE_BOTH。过滤后的数字键若不连续,再用 array_values() 重排。

为什么无回调写法会误删零值

无回调调用看起来简洁:

 0,
    'code' => '0',
    'enabled' => false,
    'note' => '',
    'name' => 'php',
];

$result = array_filter($input);
print_r($result); // 只剩 name,原来的键名仍会保留
?>

这不是“键被丢了”,而是值先被判定为空。PHP 官方手册说明,array_filter() 会保留通过筛选的原键;无回调时,判断规则等同于检查空值。

array_filter 无回调和严格回调处理零值的静态关系说明图
图1:array_filter 语义说明图,展示无回调筛选与严格回调之间的边界。

用回调明确保留整数 0

如果业务含义是“只排除 null,0 仍然是有效数量”,就不要依赖真假转换。使用严格比较可以把规则写清楚:

 0,
    'price' => 12.5,
    'missing' => null,
    'code' => '0',
];

$notNull = array_filter(
    $input,
    static fn ($value): bool => $value !== null
);

print_r($notNull); // count、price、code 保留,原键不变
?>

若只保留整数零和正数,可以把条件改成 is_int($value) && $value >= 0;若字符串 '0' 也有效,就把字符串规则单独写出来。关键是不要使用宽松的“转成布尔值再判断”,否则合法的 0 很容易和无效空值混在一起。

按键过滤后怎样得到连续列表

默认回调只收到值。只按键筛选时传入 ARRAY_FILTER_USE_KEY;需要同时读取键和值时传入 ARRAY_FILTER_USE_BOTH,参数顺序是值在前、键在后:

 str_starts_with($key, 'meta_'),
    ARRAY_FILTER_USE_KEY
);

// 同时判断键和值;第二个参数才是 key。
$valid = array_filter(
    $input,
    static fn ($value, string $key): bool =>
        str_starts_with($key, 'meta_') && $value !== null,
    ARRAY_FILTER_USE_BOTH
);

// array_filter 保留原键,输出 JSON 列表前重新编号。
$list = array_values($valid);
echo json_encode($list, JSON_UNESCAPED_UNICODE);
?>

例如原数组的数字键是 1、3、6,过滤后仍可能是 1、3、6。直接编码时它更像 JSON 对象,而不是从 0 开始的列表;array_values() 只负责重排键,不改变值的筛选结果。

array_filter 键值回调和 array_values 连续索引的静态关系说明图
图2:键和值处理说明图,展示保留原键与重排列表索引的不同职责。

这几个边界要先记住

  • 保留键不是连续索引。关联数组通常应该保留键;只有要输出 JSON 数组或按下标遍历时,才调用 array_values()。
  • 回调参数顺序别写反。ARRAY_FILTER_USE_BOTH 的回调收到的是 value, key,不是 key, value。
  • 不要在回调里修改原数组。官方手册将这种行为列为未定义行为;需要修改时先生成结果,再进行下一步处理。
  • 空回调与业务回调用途不同。空回调适合清理通用空值,涉及 0、'0'、false 的业务字段时应显式写规则。

常见问题

array_filter 会自动重新排序键吗?

不会。它保留通过筛选元素的原键,数字键可能出现间隙;需要连续索引时使用 array_values()。

怎样只按键名筛选,不让值参与判断?

把 ARRAY_FILTER_USE_KEY 作为第三个参数传入,回调只接收 key。

保留 0 时最安全的写法是什么?

先定义要排除的值,例如只排除 null 就使用 $value !== null;不要直接使用无回调版本或宽松真假判断。

把“筛选值”“保留原键”和“重排索引”拆成三个决定,array_filter() 的行为就不会再混淆:回调决定留下什么,函数保留原键,array_values() 决定是否转成连续列表。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>