Splatpacking 与 array_values() 使用数字键重新索引数组
Splatpacking versus array_values() to re-index an array with numeric keys
从 PHP7.4 开始,有一种新的技术可以使用数字键重新索引数组。
我将其称为“数组重新打包”或者类似“splatpacking”这样有趣的名称。简单的过程涉及使用 splat 运算符(...
)——又名 "spread operator"——解压缩一个数组,然后通过 "symmetric array destructuring".[=24 用第一级元素填充一个新数组=]
- RFC: Spread Operator in Array Expression
- The spread operator became available in PHP5.6
- Symmetric Array Destructuring became available in PHP7.1
- Laravel 新闻:Spread Operator for Arrays Coming to PHP 7.4
比较码:(Demo)
$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()
与新可用技术的比较。
这不同于:
- Re-index numeric array keys
- How do you reindex an array in PHP?
- PHP reindex array? [duplicate]
- array_unique and then renumbering keys [duplicate]
以及其他几十个询问如何重新索引数组的旧页面。
重新索引第一个元素未设置的 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 个字符。
这两种方法之间存在性能差异(如), but this is not the main difference between these two approaches. After all you should remember the famous quote:
所示
premature optimization is the root of all evil - DONALD E. KNUTH
可能会在下一个 PHP 版本中对 splat 运算符进行一些性能优化,它会比 array_values()
更快。除非你真的需要从你的代码中挤出最大的性能,否则我建议不要担心重新索引数百万个值所花费的时间。相反,让我们考虑一下这两种方法的共同点或不同点。
Splat 运算符只能用于数字索引。如果您的数组包含字符串键(即使是空字符串),那么 splat 运算符将阻塞并抛出异常:
Fatal error: Uncaught Error: Cannot unpack array with string keys
如果你想用数字索引重新索引你的数组,那么更安全的选择是使用 array_values()
。它适用于数值数组和关联数组。
在某些情况下,您可能需要将 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);
当然,这完全取决于您,您更喜欢哪种方法。
array_values()
不适用于 generators/iterators。如果您想解压一个生成器,您可以使用 splat 运算符。例如:
function arrGen() {
for($i = 11; $i < 15; $i++) {
yield $i**2 => $i;
}
}
$it = arrGen();
$reindexed_array = [...$it];
Splat 运算符方式不仅允许您重新索引数组,还可以在前面或附加额外的值。您也可以将两个数组合并为 1。它比 array_values()
更健壮。例如:
$arr = ['someValue', 2=> 'Not 2', 3];
$r1 = ['I am number 1!', ...$arr];
var_dump($r1);
一种方法胜过另一种方法的情况可能更多。最后,由开发人员根据具体情况决定何时使用哪个选项。
从 PHP7.4 开始,有一种新的技术可以使用数字键重新索引数组。
我将其称为“数组重新打包”或者类似“splatpacking”这样有趣的名称。简单的过程涉及使用 splat 运算符(...
)——又名 "spread operator"——解压缩一个数组,然后通过 "symmetric array destructuring".[=24 用第一级元素填充一个新数组=]
- RFC: Spread Operator in Array Expression
- The spread operator became available in PHP5.6
- Symmetric Array Destructuring became available in PHP7.1
- Laravel 新闻:Spread Operator for Arrays Coming to PHP 7.4
比较码:(Demo)
$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()
与新可用技术的比较。
这不同于:
- Re-index numeric array keys
- How do you reindex an array in PHP?
- PHP reindex array? [duplicate]
- array_unique and then renumbering keys [duplicate]
以及其他几十个询问如何重新索引数组的旧页面。
重新索引第一个元素未设置的 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 个字符。
这两种方法之间存在性能差异(如
premature optimization is the root of all evil - DONALD E. KNUTH
可能会在下一个 PHP 版本中对 splat 运算符进行一些性能优化,它会比 array_values()
更快。除非你真的需要从你的代码中挤出最大的性能,否则我建议不要担心重新索引数百万个值所花费的时间。相反,让我们考虑一下这两种方法的共同点或不同点。
Splat 运算符只能用于数字索引。如果您的数组包含字符串键(即使是空字符串),那么 splat 运算符将阻塞并抛出异常:
Fatal error: Uncaught Error: Cannot unpack array with string keys
如果你想用数字索引重新索引你的数组,那么更安全的选择是使用
array_values()
。它适用于数值数组和关联数组。在某些情况下,您可能需要将
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);
当然,这完全取决于您,您更喜欢哪种方法。
array_values()
不适用于 generators/iterators。如果您想解压一个生成器,您可以使用 splat 运算符。例如:function arrGen() { for($i = 11; $i < 15; $i++) { yield $i**2 => $i; } } $it = arrGen(); $reindexed_array = [...$it];
Splat 运算符方式不仅允许您重新索引数组,还可以在前面或附加额外的值。您也可以将两个数组合并为 1。它比
array_values()
更健壮。例如:$arr = ['someValue', 2=> 'Not 2', 3]; $r1 = ['I am number 1!', ...$arr]; var_dump($r1);
一种方法胜过另一种方法的情况可能更多。最后,由开发人员根据具体情况决定何时使用哪个选项。