-6

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

我将其称为“数组重新打包”,或者可能是一些有趣的东西,例如“ splatpacking ”。简单的过程涉及使用 splat 运算符 ( ...) - 也称为“扩展运算符” - 解包一个数组,然后通过“对称数组解构”用第一级元素填充一个新数组。

比较代码:(演示

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

var_export(array_values($array));
var_export([...$array]);

两者都会输出:

array (
  0 => 4,
  1 => 3,
  2 => NULL,
  3 => 'foo',
)

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

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

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

这不同于:

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

4

2 回答 2

6

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

过早的优化是万恶之源 - DONALD E. KNUTH

可能在下一个 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);
    

    当然,这完全取决于您,您更喜欢哪种方法。

  3. array_values()不适用于生成器/迭代器。如果你想解压一个生成器,你可以使用 splat 操作符。例如:

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

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

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

于 2020-03-15T15:20:54.053 回答
1

重新索引第一个元素未设置的 450,000 元素数组时...

array_values() 始终是 splatpacking 的两倍。

$array = range(0, 450000);
unset($array[0]);

基准脚本

样本输出:

Duration of array_values: 15.328378677368
Duration of splat-pack: 29.623107910156

在性能方面,您应该始终使用array_values(). 这是函数调用技术比非函数调用技术更有效的一种情况。


我想 splatpacking 技术获胜的唯一情况是如果你是CodeGolfer —— 13 个字符对 5 个字符。

于 2019-08-30T11:21:53.560 回答