I want to populate a result array containing values randomly drawn from an input array, but the result array must not have two identical consecutive values.
Additional rules:
Sample input:
$array = ['one', 'two', 'three', 'four'];
$n = 10;
A non-exhaustive list of possible valid results:
["three","one","three","one","two","one","four","one","three","four"]
["four","three","two","one","two","four","one","three","two","one"]
["two","four","three","one","two","one","four","two","three","one"]
How can I do this?
This question was inspired by this deleted question which struggled to ask the question with clear rules and expectations.
To guarantee that the two consecutive values are not the same, keep track of the previous value (or its key) and remove it as a possible random value for the current iteration. Push the random value into the result array, then update the "previous" variable.
array_diff_key()
can be used to exclude a specific key before calling array_rand()
to return the random key.
Code: (Demo) (Reduced alternative) (The ugly version)
$lastIndex = -1;
$result = [];
for ($x = 0; $x < $n; ++$x) {
$key = array_rand(array_diff_key($array, [$lastIndex => null]));
$result[] = $array[$key];
$lastIndex = $key;
}
echo json_encode($result);
Alternatively, you can use unset()
to exclude the previous random value, but it is important to not modify the original array or else there may not be enough values to fill the result array. Modifying a copy of the input array will do.
Code: (Demo)
$lastIndex = -1;
$result = [];
for ($x = 0; $x < $n; ++$x) {
$copy = $array;
unset($copy[$lastIndex]);
$key = array_rand($copy);
$result[] = $copy[$key];
$lastIndex = $key;
}
echo json_encode($result);
A brute force script can guess, check, and overwrite a pushed consecutive duplicate value -- this will not have a finite number of loops. Consecutive duplicates will be increasingly probable with smaller input arrays.
In the loop, unconditionally push the randomly fetched value into the result array, then only conditionally increment the counter variable if the result array has a solitary value or the last two values are different. (Demo)
$result = [];
for ($x = 0; $x < $n; $x += (int) (!$x || $result[$x] !== $result[$x - 1])) {
$result[$x] = $array[array_rand($array)];
}
echo json_encode($result);