Is there a function in PHP to do this? Or would it have to be created?
generating non-repeating random numbers from a range
Why ask? Why not browse through the manual and find [man]array_rand[/man] for yourself?
I'm trying to allow for no repeats.
I believe this should do it...
<?php
function nonRepeat($min,$max,$count) {
//prevent function from hanging
//due to a request of more values than are possible
if($max - $min < $count) {
return false;
}
$nonrepeatarray = array();
for($i = 0; $i < $count; $i++) {
$rand = rand($min,$max);
//ensure value isn't already in the array
//if it is, recalculate the rand until we
//find one that's not in the array
while(in_array($rand,$nonrepeatarray)) {
$rand = rand($min,$max);
}
//add it to the array
$nonrepeatarray[$i] = $rand;
}
return $nonrepeatarray;
}
//give it a test run
$test = nonRepeat(0,20,20);
echo "<pre>";
print_r($test);
echo "</pre>";
?>
it works man
That'll work fine for smaller arrays, but for very large ones, with $count also large, it could get really slow. This version will avoid that, while also not having to stumble on frequent duplicates:
function non_repeat($min, $max, $count)
{
if ($max - $min < $count) {
return false;
}
$arr = range($min, $max);
shuffle($arr);
$nonrepeatarray = array_slice($arr, 0, $count);
return $nonrepeatarray;
}
To avoid repeats you can also use [man]array_rand[/man].... I did mention array_rand at some stage didn't I?
An array_rand() version:
function non_repeat($min, $max, $count, $sort = false)
{
if ($max - $min < $count) {
return false;
}
$arr = range($min, $max);
$arr_rnd = array_rand($arr, $count);
foreach ($arr_rnd as $each) {
$nonrepeatarray[] = $arr[$each];
}
if (!$sort) {
shuffle($nonrepeatarray);
}
return $nonrepeatarray;
}
$test = non_repeat(16, 32, 8);
echo '<pre>';
print_r($test);
echo '</pre>';
Oh, that's overcomplicated
function sample($min,$max,$count)
{
// Trivial cases
if($count>$max-$min+1) return false; // unsatisfiable
if($count<=0) return array();
if($min==$max) return array($min);
if($count==1) return array(mt_rand($min,$max));
return array_rand(array_flip(range($min,$max)), $count);
}
But this is assuming much more about the problem than was given in the question. For all it said the following might have been what was wanted:
function no_repeats($source=null)
{
static $reserve = null;
static $backup = null;
if(is_array($source))
{
$backup = $reserve = $source;
shuffle($reserve);
return;
}
if(count($reserve)==0)
{
$reserve = $backup;
shuffle($reserve);
}
return array_shift($reserve);
}
no_repeats(range(1,100));
for($i=0; $i<20; $i++)
echo no_repeats(),' ';
I couldn't figure out how to use array_flip() for this, and the count-checking is needed even if it wasn't originally asked for. As well, the one-liner style does save code storage space. Thanks for showing us that.
Quoting myself:
An array_rand() version
Well yeah; obviously there are an infinite number of solutions, both with and without using array_rand(). I think my main beef was reading this
I'm trying to allow for no repeats.
as though array_rand didn't help with that.