rand(1,N)
but excluding array(a,b,c,..)
,
is there already a built-in function that I don\'t know or do I have to implement it myself(how?)
What you need to do is calculate an array of skipped locations so you can pick a random position in a continuous array of length M = N - #of exceptions
and easily map it back to the original array with holes. This will require time and space equal to the skipped array. I don't know php from a hole in the ground so forgive the textual semi-psudo code example.
i
elements in the original array.r
, in 0..M
the number of remaining elements.i
such that Offset[i] <= r < Offest[i+i]
this is easy with a binary searchr + i
Now, that is just a sketch you will need to deal with the ends of the arrays and if things are indexed form 0 or 1 and all that jazz. If you are clever you can actually compute the Offset array on the fly from the original, it is a bit less clear that way though.
I don't think there's such a function built-in ; you'll probably have to code it yourself.
To code this, you have two solutions :
The simplest way...
<?php
function rand_except($min, $max, $excepting = array()) {
$num = mt_rand($min, $max);
return in_array($num, $excepting) ? rand_except($min, $max, $excepting) : $num;
}
?>
No built-in function, but you could do this:
function randWithout($from, $to, array $exceptions) {
sort($exceptions); // lets us use break; in the foreach reliably
$number = rand($from, $to - count($exceptions)); // or mt_rand()
foreach ($exceptions as $exception) {
if ($number >= $exception) {
$number++; // make up for the gap
} else /*if ($number < $exception)*/ {
break;
}
}
return $number;
}
That's off the top of my head, so it could use polishing - but at least you can't end up in an infinite-loop scenario, even hypothetically.
Note: The function breaks if $exceptions
exhausts your range - e.g. calling randWithout(1, 2, array(1,2))
or randWithout(1, 2, array(0,1,2,3))
will not yield anything sensible (obviously), but in that case, the returned number will be outside the $from
-$to
range, so it's easy to catch.
If $exceptions
is guaranteed to be sorted already, sort($exceptions);
can be removed.
Eye-candy: Somewhat minimalistic visualisation of the algorithm.
This is the fastest & best performance way to do it :
$all = range($Min,$Max);
$diff = array_diff($all,$Exclude);
shuffle($diff );
$data = array_slice($diff,0,$quantity);
Maybe its too late for answer, but I found this piece of code somewhere in my mind when trying to get random data from Database based on random ID excluding some number.
$excludedData = array(); // This is your excluded number
$maxVal = $this->db->count_all_results("game_pertanyaan"); // Get the maximum number based on my database
$randomNum = rand(1, $maxVal); // Make first initiation, I think you can put this directly in the while > in_array paramater, seems working as well, it's up to you
while (in_array($randomNum, $excludedData)) {
$randomNum = rand(1, $maxVal);
}
$randomNum; //Your random number excluding some number you choose