Reputation: 191
How do you shuffle an array in PHP but preserve the order of the shuffle when an element is inserted or deleted like mysql order by rand(seed) does? A kind of Fisher-Yates shuffle algorithm that ignores the length of the array.
Lets assume you have an array with A,B,C and you run this:
SELECT *
FROM (
SELECT 'A' AS value
UNION
SELECT 'B' AS value
UNION
SELECT 'C' AS value) AS T order by rand(123)
The result will be B,C,A.
Now if you add D to the list of elements:
SELECT *
FROM (
SELECT 'A' AS value
UNION
SELECT 'B' AS value
UNION
SELECT 'C' AS value
UNION
SELECT 'D' AS value) AS T order by rand(123)
The result will be D,B,C,A.
Adding element E to the list:
SELECT *
FROM (
SELECT 'A' AS value
UNION
SELECT 'B' AS value
UNION
SELECT 'C' AS value
UNION
SELECT 'D' AS value
UNION
SELECT 'E' AS value) AS T order by rand(123)
The result will be D,B,C,E,A.
Fisher-Yates will provide a totally different order when you add the element "D" to the array, while mysql order by rand(seed) will insert element "D" somewhere in the already random sorted list.
Upvotes: 1
Views: 561
Reputation: 214949
You can mimic sort-by-rand behavior in a way similar to this:
function sort_by_rand($ary, $seed) {
srand($seed);
$tmp = array_map(function($x) { return [rand(), $x]; }, $ary);
sort($tmp);
return array_map(function($x) { return $x[1]; }, $tmp);
}
Results:
$ary = ['A', 'B', 'C'];
print_r(sort_by_rand($ary, 100)); // CBA
$ary = ['A', 'B', 'C', 'D'];
print_r(sort_by_rand($ary, 100)); // CBAD
$ary = ['A', 'B', 'C', 'D', 'E'];
print_r(sort_by_rand($ary, 100)); // CBAED
Upvotes: 3