Splatpacking 与 array_values() 使用数字键重新索引数组

mic*_*usa -6 php arrays argument-unpacking reindex php-7.4

从 PHP7.4 开始,有一种新的技术可以使用数字键重新索引数组。

我会称它为“数组重新打包”或者一些有趣的东西,比如“ splatpacking ”。简单的过程包括使用 splat 运算符 ( ...) —— 又名“扩展运算符”——来解包一个数组,然后通过“对称数组解构”用第一级元素填充一个新数组。

比较代码:(演示

$array = [2 => 4, 5 => 3, "3" => null, -10.9 => 'foo'];

var_export(array_values($array));
var_export([...$array]);
Run Code Online (Sandbox Code Playgroud)

两者都会输出:

array (
  0 => 4,
  1 => 3,
  2 => NULL,
  3 => 'foo',
)
Run Code Online (Sandbox Code Playgroud)

同样,splatpacking 技术严格限于带有数字键的数组,因为 splat 运算符会阻塞其他任何东西,并且只有 PHP7.4 及更高版本才能将解压缩的值直接写入数组。

由于这两种技术在排位赛中提供相同的输出,我什么时候应该使用一种而不是另一种?

请注意,这不是关于如何重新索引键,而是array_values()与新可用技术的比较。

这不同于:

以及其他几十个询问如何重新索引数组的旧页面。

Dha*_*man 5

这两种方法之间存在性能差异(如另一个答案所示),但这不是这两种方法之间的主要区别。毕竟你应该记住那句名言

过早的优化是万恶之源——唐纳德·E·克努斯

可能是在下一个 PHP 版本中,splat 运算符会获得一些性能优化,并且它会比array_values(). 除非您真的需要从代码中榨取最大的性能,否则我建议不要担心重新索引数百万个值所需的时间。相反,让我们考虑一下这两种方法的共同点或不同点。

  1. Splat 运算符只能处理数字索引。如果您的数组包含一个字符串键(甚至是一个空字符串),那么 splat 运算符将阻塞并抛出异常:

    致命错误:未捕获错误:无法使用字符串键解压数组

    如果你想用数字索引重新索引你的数组,那么更安全的选择是使用array_values(). 它适用于数值和关联数组。

  2. 可能存在需要array_value作为回调传递的情况。如果您想对 splat 运算符执行相同操作,则需要将其包装在闭包中,例如fn($arr) => [...$arr]. 使用'array_values'反而可能是一个更简单和更清洁的解决方案。例如,如果您想重新索引多维数组(只有数字键),您有以下两个选项:

    $array = [range(0, 10), range(15,25)];
    unset($array[0][1], $array[1][5]);
    
    $reindex_array = array_map('array_values', $array);
    // or
    $reindex_array = array_map(fn($arr) => [...$arr], $array);
    
    Run Code Online (Sandbox Code Playgroud)

    当然,这真的取决于你,你喜欢哪种方法。

  3. array_values()不适用于生成器/迭代器。如果您想打开生成器的包装,您可以改用 splat 运算符。例如:

    function arrGen() {
        for($i = 11; $i < 15; $i++) {
            yield $i**2 => $i;
        }
    }
    
    $it = arrGen();
    $reindexed_array = [...$it];
    
    Run Code Online (Sandbox Code Playgroud)
  4. Splat 运算符方式不仅允许您重新索引数组,还允许您添加或附加额外的值。您也可以将两个数组合并为 1。它比array_values(). 例如:

    $arr = ['someValue', 2=> 'Not 2', 3];
    $r1 = ['I am number 1!', ...$arr];
    
    var_dump($r1);
    
    Run Code Online (Sandbox Code Playgroud)

一种方法胜过另一种方法的情况可能更多。最后,由开发人员根据情况决定何时使用哪个选项。