Reputation: 48031
As of PHP7.4, there is a newly available technique to re-index an array with numeric keys.
I'll call it "array re-packing" or maybe something fun like "splatpacking". The simple process involves using the splat operator (...
) -- aka "spread operator" -- to unpack an array then filling a new array with the first-level elements via "symmetric array destructuring".
Comparison Code: (Demo)
$array = [2 => 4, 5 => 3, "3" => null, -10.9 => 'foo'];
var_export(array_values($array));
var_export([...$array]);
Both will output:
array (
0 => 4,
1 => 3,
2 => NULL,
3 => 'foo',
)
Again, the splatpacking technique is strictly limited to arrays with numeric keys because the splat operator chokes on anything else AND the ability to write the unpacked values directly into an array is only available from PHP7.4 and higher.
With the two techinques delivering the same output in qualifying situations, when should I use one over the other?
Note, this is not about how to reindex keys, but a comparison of array_values()
versus a newly available technique.
This is different from:
and the other tens of old pages that ask how to reindex an array.
Upvotes: -5
Views: 1603
Reputation: 48031
When re-indexing a 450,000 element array which has its first element unset...
Before PHP8.3, array_values() is consistently twice as fast as splatpacking.
$array = range(0, 450000);
unset($array[0]);
Sample output:
Duration of array_values: 15.328378677368
Duration of splat-pack: 29.623107910156
In terms of performance, before PHP8.3 you should always use array_values()
. This is one case when a function-calling technique is more efficient than a non-function-calling technique.
As of PHP8.3 (proven by my old benchmarking script), the performance difference between the two techniques has become negligible (no longer a concern).
I suppose the only scenario where the splatpacking technique wins is if you are a CodeGolfer -- 13 characters versus 5.
Upvotes: 4
Reputation: 33400
There is a performance difference between these two methods (as shown in the other answer), 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
It could be that in the next PHP release the splat operator gets some performance optimization and it will be faster than array_values()
. Unless you really need to squeeze out the most performance from your code, I would recommend to not worry about the time it takes to re-index millions of values. Instead let's consider what both of these approaches have in common or don't.
Prior to PHP 8.1, splat operator can only work with numerical indices. If your array contains a string key (even an empty string) then splat operator will choke and throw an exception:
Fatal error: Uncaught Error: Cannot unpack array with string keys
If you would like to re-index your array with numerical indices, then the safer option is to use array_values()
. It works for both numerical and associative arrays.
There might be situations when you need to pass array_value
as a callback. If you wanted to do the same with the splat operator you would need to wrap it in closure e.g. fn($arr) => [...$arr]
. Using 'array_values'
instead could be a simpler and cleaner solution. For example if you wanted to re-index multi-dimensional array (having only numerical keys) you have these two options:
$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);
Of course it's really up to you, which approach you prefer.
array_values()
does not work with generators/iterators. If you would like to unpack a generator you can use the splat operator instead. For example:
function arrGen() {
for($i = 11; $i < 15; $i++) {
yield $i**2 => $i;
}
}
$it = arrGen();
$reindexed_array = [...$it];
Splat operator way allows you not only to re-index the array, but also prepend or append extra values. You could also merge two arrays into 1. It is more robust than array_values()
. For example:
$arr = ['someValue', 2=> 'Not 2', 3];
$r1 = ['I am number 1!', ...$arr];
var_dump($r1);
There's probably more scenarios where one approach wins over the other. In the end it is up to the developer to decide when to use which option, based on the circumstances.
Upvotes: 8