为什么使用null作为回调函数的array_map()会创建一个“数组的数组”?

9

今天我学习了PHP中array_map()的一个特殊用法,这在文档的旁注中提到:

Example #4 Creating an array of arrays

<?php
$a = array(1, 2, 3, 4, 5);
$b = array("one", "two", "three", "four", "five");
$c = array("uno", "dos", "tres", "cuatro", "cinco");

$d = array_map(null, $a, $b, $c);
print_r($d);
?>

The above example will output:

Array
(
    [0] => Array
        (
            [0] => 1
            [1] => one
            [2] => uno
        )

    [1] => Array
        (
            [0] => 2
            [1] => two
            [2] => dos
        )

    [2] => Array
        (
            [0] => 3
            [1] => three
            [2] => tres
        )

    [3] => Array
        (
            [0] => 4
            [1] => four
            [2] => cuatro
        )

    [4] => Array
        (
            [0] => 5
            [1] => five
            [2] => cinco
        )

)

If the array argument contains string keys then the returned array will contain string keys if and only if exactly one array is passed. If more than one argument is passed then the returned array always has integer keys.

(试一下)

但就是这样。没有更多的解释了。我理解,这与以下代码的作用相同:

$d = array_map(function() { return func_get_args(); }, $a, $b, $c);

但是为什么有人希望或者期望这是默认行为呢?是否有技术原因导致它工作方式如此,例如从实现的副作用中?还是只是随意决定“让这个函数做更多的事情”(看看你,array_multisort())?


1
我猜那就是它的实现方式,而且既然他们已经记录下来了,这可能不是一个“副作用”。另外,使用这个方法旋转一个数组也非常方便! - Rizier123
你的问题也可以简化为:“为什么它被称为array_map()而不是call_function_for_each_array_element()?”只有实现它的开发者才能告诉你这个问题的答案。但是,为什么有人会希望或期望这种默认行为呢?为什么你期望第一个参数默认是回调函数呢? - Rizier123
因为它很棒! - user1842104
2个回答

5
这似乎是_array_map_中的一个特殊情况,但这只在示例中有记录。NULL通常不允许作为回调函数(如果您尝试在call_user_func()中使用它会报错),但在_array_map()_中允许使用。它将NULL视为仅创建参数数组。
这很有用,因为array也不能作为回调函数,因为它是语言结构而不是函数。所以您无法编写:
$d = array_map('array', $a, $b, $c);

说实话,我没有想到null代表“回调函数”的意思是数组,但这种推理在某种程度上是有道理的。 - Fabian Schmengler

3

array_map(null, ...[arrays]) 执行"转置"操作。有些人将此重新定位称为“对角线翻转”,但它在功能上相当于将数据的列转换为行。

即使在最新版本的 PHP(截至本文发布时为 8.1),此不直观的原生技术仅适用于数字键入数组的数字键入数组,只要有多个行(子数组)。

为了清晰起见,在 array_map(null, ...[$a, $b, $c]) 中展开运算符的实现基本上与 array_map(null, $a, $b, $c) 相同。

使用此技术来准备数据进行图形或表格表示的开发人员喜欢简洁(尽管晦涩)的语法 - 它比拼写两个嵌套的 foreach 循环更加吸引人。

这些开发人员可能会惊讶地发现,当没有多行数据需要转置时,原始的 2D 数组会被缩小为 1D 数组。在这种情况下,null 参数版本与 func_get_args() 版本不相同。

代码:(演示)

$array = [
    [1 => 'one', 2 => 'two', 3 => 'three']
];
var_export(array_map(fn() => func_get_args(), ...$array));
echo "\n---\n";
var_export(array_map(null, ...$array));

输出:

array (
  1 => 
  array (
    0 => 'one',
  ),
  2 => 
  array (
    0 => 'two',
  ),
  3 => 
  array (
    0 => 'three',
  ),
)
---
array (
  1 => 'one',
  2 => 'two',
  3 => 'three',
)

总的来说,我无法代表开发者解释为什么这种 array_map() 技术要以这种方式设计,但我想在此刻警告开发者不要被它的魅力所迷惑。它会破坏数字键和它们的值之间的关联关系,可能会意外地压缩输出数组。换句话说,请确保你的数据适合使用这种技术,因为这种技术并不适用于所有数据。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接