使用匿名函数回调根据值拆分数组

JRL*_*JRL 3 php arrays split callback

给定一个$arr以下形式的数组:

Array (
    [0] => Array ([id] => id1, ...)
    [1] => Array ([id] => id1, ...)
    [2] => Array ([id] => id2, ...)
    ...
)
Run Code Online (Sandbox Code Playgroud)

使用这个 foreach 循环:

$rowsById = [];
foreach ($arr as $row) {
    $rowsById[$row['id']][] = $row;
}
Run Code Online (Sandbox Code Playgroud)

我们可以将其转换为以下形式的数组(以 ids 为键):

Array (
    [id1] => Array (
                 [0] => Array ([id] => id1, ...)
                 [1] => Array ([id] => id1, ...)
             )
    [id2] => Array (
                 [0] => Array ([id] => id2, ...)
             )
    ...
)
Run Code Online (Sandbox Code Playgroud)

我们可以做同样的事情但没有 foreach 循环吗? (也就是说,使用一些迭代函数,如 array_walk 和回调)

Wal*_*oss 6

$map = array();
array_walk($arr, function($row, $i) use(&$map) { $map[$row['id']][] = $row; });
Run Code Online (Sandbox Code Playgroud)

从形式上看,这个解决方案是对你的问题的肯定回答。

但是,如果您想加快代码速度,或者即使您想要更清晰的代码而不在其他地方丢失太多内容,那么令人惊讶的是:这个解决方案肯定比您的循环慢(在我的机器上慢了3foreach倍)。几乎可以肯定,原因是对匿名函数的函数调用,而 foreach 解决方案中不存在该函数调用。正如我在另一个答案中已经指出的那样,函数调用消耗了 CPU 时间

如果我们可以组合简单的array_函数来获得相同的结果,这种情况可能会有所不同,但事实上['id']必须以某种方式访问​​,创建中间数组的开销,加上没有array_函数可用于直接分配给键控箱的事实,使得这是一项不可能完成的任务。

例如,我在意识到错误之前发布的这段代码因为它替换而不是附加到垃圾箱)

$map = array_combine(array_map(function($a) { return $a['id']; }, $arr), $arr);
Run Code Online (Sandbox Code Playgroud)

在我的机器上运行速度比你的慢2.5foreach倍。

因此,最后,您问题的答案是:“是的,如果我们不关心处理时间”。