I have the following code to pick $n
elements from an array $array
in PHP:
shuffle($array);
$result = array_splice($array, 0, $n);
Given a large array but only a few elements (for example 5
out of 10000
), this is relatively slow, so I would like to optimize it such that not all elements have to be shuffled. The values must be unique.
I'm looking fo the most performant alternative. We can assume that $array
has no duplicates and is 0
-indexed.
This function performs a shuffle on only $n
elements where $n
is the number of random elements you want to pick. It will also work on associative arrays and sparse arrays. $array
is the array to work on and $n
is the number of random elements to retrieve.
If we define the $max_index
as count($array) - 1 - $iteration
.
It works by generating a random number between 0 and $max_index
. Picking the key at that index, and replacing its index with the value at $max_index
so that it can never be picked again, as $max_index
will be one less at the next iteration and unreachable.
In summary this is the Richard Durstenfeld's Fisher-Yates shuffle but operating only on $n
elements instead of the entire array.
function rand_pluck($array, $n) {
$array_keys = array_keys($array);
$array_length = count($array_keys);
$max_index = $array_length -1;
$iterations = min($n, $array_length);
$random_array = array();
while($iterations--) {
$index = mt_rand(0, $max_index);
$value = $array_keys[$index];
$array_keys[$index] = $array_keys[$max_index];
array_push($random_array, $array[$value]);
$max_index--;
}
return $random_array;
}
$randomArray = [];
while (count($randomArray) < 5) {
$randomKey = mt_rand(0, count($array)-1);
$randomArray[$randomKey] = $array[$randomKey];
}
This will provide exactly 5 elements with no duplicates and very quickly. The keys will be preserved.
Note: You'd have to make sure $array had 5 or more elements or add some sort of check to prevent an endless loop.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With