In my php script, I have a variable $data that contains an array that may have various number of elements.
The script picks one of the array elements at random and outputs it to the browser:
# count number of elements in $data
$n = count($data);
# pick a random number out of the number of elements in $data
$rand = rand(0, ($n - 1));
# output a random element
echo '<p> . trim($data[$rand]) . '</p>';
QUESTION: I want to improve that script, so that it doesn't output the same array element again until it runs out of array elements. For example, if an array contains elements numbered 0 to 9, and the script picked an array element #4, I want it to remember that, and next time the script runs, to exclude the element that was #4.
It could probably be done in many different ways, but I'm looking for the simplest and most elegant solution, and would be grateful for help from a PHP expert.
Save the numbers that were already picked in the user's session.
session_start();
$n = count($data);
// If the array isn't initialized, or we used all the numbers, reset the array
if( !isset( $_SESSION['used_nums']) || count( $_SESSION['used_nums']) == $n) {
$_SESSION['used_nums'] = array();
}
do{
$rand = rand(0, ($n - 1));
} while( isset( $_SESSION['used_nums'][$rand]));
echo '<p>' . trim($data[$rand]) . '</p>';
$_SESSION['used_nums'][$rand] = 1;
Or, perhaps a more clever way, using array_intersect_key
and array_rand
:
session_start();
$n = count($data);
// If the array isn't initialized, or we used all the numbers, reset the array
if( !isset( $_SESSION['used_nums']) || count( $_SESSION['used_nums']) == $n) {
$_SESSION['used_nums'] = array();
}
$unused = array_intersect_key( $data, $_SESSION['used_nums'];
$rand = array_rand( $unused);
echo '<p>' . trim($unused[$rand]) . '</p>';
$_SESSION['used_nums'][$rand] = 1;
$selection=$x[$randomNumber];
unset($x[$randomNumber]);
You can use sessions to store the indexes you've used so far. Try this.
session_start();
$used = &$_SESSION['usedIndexes'];
// used all of our array indexes
if(count($used) > count($data))
$used = array();
// remove the used indexes from data
foreach($used as $index)
unset($data[$index]);
$random = array_rand($data);
// append our new index to used indexes
$used[] = $random;
echo '<p>', trim($data[$random]) ,'</p>';
You could shuffle the array and then simply iterate over it:
shuffle($data);
foreach ($data as $elem) {
// …
}
If you don’t want to alter the array order, you could simply shuffle the array’s keys:
$keys = array_keys($data);
shuffle($keys);
foreach ($keys as $key) {
// $data[$key]
}