array_map($callback, $array) 对 $array 的每个元素调用 $callback,并返回一个由结果组成的新数组。回调函数是第一个参数,数组是第二个参数,原数组保持不变。
fn($p) => $p * 1.2 是一个箭头函数:只有一个表达式、并返回其结果的函数。任何 callable 都可以放在它的位置上。
用内置函数作为回调函数
把内置函数的名字作为字符串传入。这是清理整个数组最简短的方式:去掉每个值两端的空格、把字符串转换成整数,或者改变大小写。
array_map('intval', ...) 是把来自表单或 explode() 的字符串转换成真正整数的常用写法。你也可以写成 intval(...),这是 PHP 8.1 的一等可调用语法,编辑器可以自动补全并检查它。
使用引用外部变量的闭包
箭头函数会自动看到它周围的变量。传统的 function 需要用 use 把它们引入。两者在匿名函数一页中都有讲解。
带键的 array_map
只传一个数组时,array_map 会保留键,包括字符串键。但回调函数只能收到值。要同时拿到键,就把 array_keys($array) 作为第二个数组传入:这样每次调用回调函数时,都会从每个数组中各取一个元素。
注意第二个结果:只要传入多于一个数组,键就会被替换成 0, 1, 2。所以最后一行用 array_combine() 把键重新建立起来。
同时映射多个数组
每多一个数组,回调函数就多一个参数,按位置一一对应。如果数组长度不同,较短的数组会用 null 补齐。
把 null 作为回调函数传入,就会跳过函数调用,把几个数组按位置组合成一对一对的元素:
array_map、array_walk 和 foreach 的对比
array_map 生成一个新数组。array_walk 通过引用修改你传入的数组,并把键作为第二个参数传给回调函数。foreach 两种都能做,还可以跳过某些元素,或者用 break 提前结束。
当每个元素都恰好变成一个新元素时,用 array_map。如果还需要去掉一些元素,就把它和 array_filter 结合使用,或者写一个 foreach。
常见错误:参数顺序
array_map 的第一个参数是回调函数,第二个是数组。和它相邻的 array_filter 顺序正好相反,很容易搞混:
array_map($callback, $array); // callback first
array_filter($array, $callback); // array first
把它们调换后,PHP 8 会抛出 TypeError,因为一个普通数组不是有效的回调函数:
PHP 停止运行并输出:
PHP Fatal error: Uncaught TypeError: array_map(): Argument #1 ($callback) must be a valid callback or null, array callback must have exactly two members in /home/index.php:4
把两个参数换回来,这段代码就能运行了。
常见问题
PHP 中 array_map 有什么作用?
它对数组的每个元素调用一个函数,并返回一个由结果组成的新数组:array_map(fn($n) => $n * 2, [1, 2, 3]) 返回 [2, 4, 6]。原数组不会改变。
array_map 会保留键吗?
只传一个数组时会:字符串键和整数键都原样保留。传入两个或更多数组时,结果总是使用新的键 0, 1, 2...。
怎样在 array_map 的回调函数中拿到键?
把键作为第二个数组传入:array_map(fn($k, $v) => "$k=$v", array_keys($arr), $arr)。结果是一个列表,如果需要恢复原来的键,就用 array_combine(array_keys($arr), ...) 包一层。
array_map 比 foreach 快吗?
差别不大。两者都只遍历数组一次,而普通的 foreach 往往还稍快一点,因为它不需要为每个元素调用一次函数。当 array_map 读起来更清楚时就用它:一次转换,生成一个新数组。
array_map 和 array_walk 有什么区别?
array_map 返回一个新数组,不改动输入。array_walk 返回 true,它的用途是通过引用参数直接修改原数组:array_walk($arr, function (&$v, $k) { $v = trim($v); });。