Нет встроенной функции, но вы могли бы сделать это:
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;
}
Это не в моей голове, поэтому можно было бы использовать полировку - но, по крайней мере, вы не можете оказаться в сценарии бесконечного цикла, даже гипотетически.
Примечание : функция прерывается, если $exceptions
исчерпывает ваш диапазон - например, вызов randWithout(1, 2, array(1,2))
или randWithout(1, 2, array(0,1,2,3))
не даст ничего разумного (очевидно), но в этом случае возвращенное число будет вне диапазона $from
- $to
, поэтому его легко поймать.
Если $exceptions
гарантированно уже отсортирован, sort($exceptions);
можно удалить.
Eye-candy : Несколько минималистичная визуализация алгоритма .