PHP 面试题:PHP 数组函数 array_map、array_walk、array_filter 的区别

在 PHP 面试中,array_maparray_walkarray_filter 是三个经常被拿来对比的数组函数。它们都可以对数组中的每个元素执行某种操作,但各自的设计目的、返回值、回调参数和使用场景有显著差异。很多候选人在实际开发中能“用对”,却未必能“说清”。本文将从底层机制、典型用法和常见陷阱三个维度,帮你彻底理清它们的区别。

一、核心定位:它们各自解决什么问题

先给出最简洁的结论:

  • array_map:对数组每个元素执行回调,返回一个新数组,原数组不变。核心是“映射/转换”。
  • array_walk:对数组每个元素执行回调,返回布尔值,通常用于“就地修改”原数组。核心是“遍历并副作用操作”。
  • array_filter:用回调过滤数组元素,返回过滤后的新数组,原数组不变。核心是“筛选”。

记住这三个关键词:映射、遍历、筛选,后续所有差异都由此衍生。

二、返回值与参数签名对比

特性 array_map array_walk array_filter
返回值 新数组 bool 新数组
是否修改原数组 可修改(引用)
回调参数 值(可多数组) 值 + 键 + 额外参数 值(键可选)
支持多数组
键是否保留 否(重新索引) 不涉及 是(保留原键)
回调返回值作用 作为新值 仅作流程控制 决定是否保留

这张表建议面试时直接背下来,能覆盖 80% 的追问。

三、array_map 详解

基本用法

$arr = [1, 2, 3, 4];
$result = array_map(function($n) {
    return $n * 2;
}, $arr);
// $result = [2, 4, 6, 8]
// $arr 仍然是 [1, 2, 3, 4]

多数组同时处理

这是 array_map 独有的能力,面试常考:

$a = [1, 2, 3];
$b = [10, 20, 30];
$result = array_map(function($x, $y) {
    return $x + $y;
}, $a, $b);
// [11, 22, 33]

多数组时,长度以最长数组为准,短数组会用 null 补齐。

关键注意点

  • 如果传入 null 作为回调,array_map 会返回原数组的副本,可用于“重新索引”或“去除引用”。
  • 字符串键会被丢弃,返回数组始终是连续整数索引。这是与 array_filter 的重要区别。
  • 回调返回什么,新数组元素就是什么,返回 null 也会被保留。

四、array_walk 详解

基本用法

$arr = [1, 2, 3];
array_walk($arr, function(&$value, $key) {
    $value = $value * 2;
});
// $arr 变为 [2, 4, 6]

注意回调第一个参数是引用 &$value,这是能修改原数组的关键。如果不加 &,修改不会生效——这是面试高频陷阱。

第三个参数

array_walk 支持传入额外参数,会作为回调的第三个参数:

$arr = ['a', 'b'];
array_walk($arr, function($value, $key, $prefix) {
    echo $prefix . $value;
}, 'item_');
// 输出 item_a item_b

关键注意点

  • 返回布尔值,成功 true,失败 false。不要试图接收它的“结果数组”。
  • 回调的返回值被忽略,只用于控制流程(但实际中很少这样用)。
  • 如果要修改键,需要用 &$key,且 PHP 对键的修改支持有限,实践中不推荐。
  • 相比 foreacharray_walk 更函数式,但可读性未必更好。

五、array_filter 详解

基本用法

$arr = [1, 0, 2, null, 3, '', 4];
$result = array_filter($arr);
// [1, 2, 3, 4](默认过滤掉假值)

不传回调时,array_filter 会过滤掉所有“假值”:falsenull0''[]'0'。注意 '0'0 也会被过滤,这是常见坑。

带回调

$arr = [1, 2, 3, 4, 5];
$result = array_filter($arr, function($n) {
    return $n % 2 === 1;
});
// [1, 3, 5]

使用 ARRAY_FILTER_USE_KEY 和 ARRAY_FILTER_USE_BOTH

PHP 5.6+ 支持回调接收键:

$arr = ['a' => 1, 'b' => 2, 'c' => 3];
$result = array_filter($arr, function($key) {
    return $key !== 'b';
}, ARRAY_FILTER_USE_KEY);
// ['a' => 1, 'c' => 3]

ARRAY_FILTER_USE_BOTH 则同时传入值和键。

关键注意点

  • 保留原键。过滤后键不会重新索引,如果后续需要连续索引,要配合 array_values()
  • 回调只需返回布尔值,true 保留,false 过滤。
  • 默认行为容易误伤 0'0',过滤数字时建议显式传回调。

六、三者对比的经典面试题

题目:把数组 [1, 2, 3, 4, 5] 中的偶数翻倍,并只保留结果大于 5 的元素。

用三个函数分别实现:

$arr = [1, 2, 3, 4, 5];

// 方案一:array_map + array_filter
$step1 = array_map(fn($n) => $n % 2 === 0 ? $n * 2 : $n, $arr);
$result = array_filter($step1, fn($n) => $n > 5);
// [8, 10]

// 方案二:array_walk + array_filter
$temp = $arr;
array_walk($temp, function(&$v) {
    if ($v % 2 === 0) $v *= 2;
});
$result = array_filter($temp, fn($n) => $n > 5);

// 方案三:array_filter + array_map(顺序不同)
$filtered = array_filter($arr, fn($n) => $n % 2 === 0);
$result = array_map(fn($n) => $n * 2, $filtered);
// [4, 8] —— 注意结果不同!

这个例子说明:函数的执行顺序会影响结果,面试时可以主动指出这一点,展示你对数据流的理解。

七、性能与选择建议

  • 纯转换用 array_map,语义最清晰。
  • 纯筛选用 array_filter
  • 需要就地修改、或需要键和额外参数时用 array_walk
  • 如果只是简单遍历且不需要返回值,foreach 往往比 array_walk 更直观、性能也略好。
  • 链式调用时注意 array_filter 保留键的问题,必要时用 array_values 重置。

八、一句话总结

array_map 管“变成什么”,array_filter 管“留下什么”,array_walk 管“对每个元素做点什么”。 返回值、是否修改原数组、键的处理方式,是区分它们的三把钥匙。面试中能把这三点讲清楚,并指出 array_filter 默认过滤假值和保留键这两个陷阱,基本就能拿到高分。

未经允许不得转载:任鹏个人博客 » PHP 面试题:PHP 数组函数 array_map、array_walk、array_filter 的区别

赞 (0) 打赏

评论 0

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

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏