Как получить случайное значение от 1 ~ N, но исключая несколько конкретных значений в PHP?

rand(1,N) но исключая array(a,b,c,..)

есть ли уже встроенная функция, которую я не знаю или мне нужно ее реализовать самостоятельно (как?)?

ОБНОВИТЬ

Квалифицированное решение должно обладать золотом, независимо от того, большой или нет размер excluded array .

    Нет встроенной функции, но вы можете сделать это:

     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 range, поэтому его легко поймать.

    Если $exceptions гарантированно будет отсортировано уже, sort($exceptions); могут быть удалены.

    Eye-candy : несколько минимальная визуализация алгоритма .

    Я не думаю, что есть такая встроенная функция; вам, вероятно, придется самому закодировать его.

    Чтобы закодировать это, у вас есть два решения:

    • Используйте цикл, чтобы вызвать rand () или mt_rand (), пока он не вернет правильное значение
      • что означает вызов rand () несколько раз, в худшем случае
      • но это должно работать нормально, если N велико, и у вас нет многих запрещенных значений.
    • Создайте массив, содержащий только правовые значения
      • И используйте array_rand чтобы выбрать одно значение из него
      • который будет работать нормально, если N мало

    В зависимости от того, что вам нужно, и почему этот подход может быть интересной альтернативой.

     $numbers = array_diff(range(1, N), array(a, b, c)); // Either (not a real answer, but could be useful, depending on your circumstances) shuffle($numbers); // $numbers is now a randomly-sorted array containing all the numbers that interest you // Or: $x = $numbers[array_rand($numbers)]; // $x is now a random number selected from the set of numbers you're interested in 

    Таким образом, если вам не нужно генерировать набор потенциальных чисел каждый раз, но генерирует набор один раз, а затем выбирает кучу случайных чисел из одного и того же набора, это может быть хорошим способом.

    Самый простой способ …

     <?php function rand_except($min, $max, $excepting = array()) { $num = mt_rand($min, $max); return in_array($num, $excepting) ? rand_except($min, $max, $excepting) : $num; } ?> 

    Вам нужно вычислить массив пропущенных местоположений, чтобы вы могли выбрать случайную позицию в непрерывном массиве длиной M = N - #of exceptions и легко отобразить ее обратно в исходный массив с отверстиями. Для этого потребуется время и пространство, равные пропущенному массиву. Я не знаю php из отверстия в земле, поэтому простите текстовый пример кода полу-psudo.

    1. Сделайте новый массив Offset [] той же длины, что и массив Exceptions.
    2. in Offset [i] сохранит первый индекс в воображаемом непустоте массив, который пропустил бы i элементы в исходном массиве.
    3. Теперь выберите случайный элемент. Выберите случайное число, r , в 0..M количество оставшихся элементов.
    4. Найдите i , что Offset[i] <= r < Offest[i+i] это легко с бинарным поиском
    5. Возврат r + i

    Теперь, это всего лишь эскиз, вам нужно будет разобраться с концами массивов, и если что-то индексируется в форме 0 или 1 и во всем этом джазе. Если вы умны, вы можете фактически вычислить массив Offset на лету от оригинала, но это немного менее понятно.

    Может быть, слишком поздно для ответа, но я нашел этот кусок кода где-то в своем уме, пытаясь получить случайные данные из базы данных на основе случайного идентификатора, за исключением некоторого числа.

     $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 

    Это самый быстрый и эффективный способ сделать это:

     $all = range($Min,$Max); $diff = array_diff($all,$Exclude); shuffle($diff ); $data = array_slice($diff,0,$quantity);