Генерация уникальных случайных чисел от 1 до 100 - PullRequest
79 голосов
/ 04 марта 2010

Как я могу сгенерировать 8, скажем, уникальных случайных чисел от 1 до 100, используя JavaScript?

Ответы [ 26 ]

129 голосов
/ 04 марта 2010

var arr = []
while(arr.length < 8){
    var r = Math.floor(Math.random()*100) + 1;
    if(arr.indexOf(r) === -1) arr.push(r);
}
document.write(arr);
35 голосов
/ 04 марта 2010
  1. Заполните массив числами от 1 до 100.
  2. Перемешать это .
  3. Возьмите первые 8 элементов полученного массива.
13 голосов
/ 04 марта 2010

Создайте перестановку из 100 чисел и затем выберите последовательно.

Использование Алгоритм Кнута Шаффла (он же тасование Фишера-Йейтса) .

JavaScript:

  function fisherYates ( myArray,stop_count ) {
  var i = myArray.length;
  if ( i == 0 ) return false;
  int c = 0;
  while ( --i ) {
     var j = Math.floor( Math.random() * ( i + 1 ) );
     var tempi = myArray[i];
     var tempj = myArray[j];
     myArray[i] = tempj;
     myArray[j] = tempi;

     // Edited thanks to Frerich Raabe
     c++;
     if(c == stop_count)return;

   }
}

КОД, КОПИРОВАННЫЙ ИЗ ССЫЛКИ.

EDIT

Улучшенный код:

function fisherYates(myArray,nb_picks)
{
    for (i = myArray.length-1; i > 1  ; i--)
    {
        var r = Math.floor(Math.random()*i);
        var t = myArray[i];
        myArray[i] = myArray[r];
        myArray[r] = t;
    }

    return myArray.slice(0,nb_picks);
}

Потенциальная проблема:

Предположим, у нас есть массив из 100 чисел {например, [1,2,3 ... 100]} и мы прекращаем обмен после 8 перестановок; тогда массив в большинстве случаев будет выглядеть как {1,2,3,76,5,6,7,8, ... числа здесь будут перемешаны ... 10}.

Потому что каждое число будет поменяно местами с вероятностью 1/100, так Проб. поменять местами первые 8 чисел - 8/100, тогда как проб. обменять другой 92 - 92/100.

Но если мы запустим алгоритм для полного массива, то мы уверены (почти), что каждая запись поменялась местами.

В противном случае мы сталкиваемся с вопросом: какие 8 цифр выбрать?

10 голосов
/ 12 октября 2014

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

Специально для решения вашего вопроса, используя Chance, это так же просто, как:

// One line!
var uniques = chance.unique(chance.natural, 8, {min: 1, max: 100});

// Print it out to the document for this snippet so we can see it in action
document.write(JSON.stringify(uniques));
<script src="http://chancejs.com/chance.min.js"></script>

Отказ от ответственности, как автор Chance, я немного предвзят;)

8 голосов
/ 04 марта 2010

Чтобы избежать любых длинных и ненадежных перетасовок, я бы сделал следующее ...

  1. Создание массива, который содержит по порядку число от 1 до 100.
  2. Генерация случайного числа от 1 до 100
  3. Посмотрите число по этому индексу в массиве и сохраните в ваших результатах
  4. Удалите элемент из массива, сделав его короче
  5. Повторите с шага 2, но используйте 99 в качестве верхнего предела случайного числа
  6. Повторите с шага 2, но используйте 98 в качестве верхнего предела случайного числа
  7. Повторите с шага 2, но используйте 97 в качестве верхнего предела случайного числа
  8. Повторите с шага 2, но используйте 96 в качестве верхнего предела случайного числа
  9. Повторите с шага 2, но используйте 95 в качестве верхнего предела случайного числа
  10. Повторите с шага 2, но используйте 94 в качестве верхнего предела случайного числа
  11. Повторите с шага 2, но используйте 93 в качестве верхнего предела случайного числа

Вуаля - без повторяющихся чисел.

Я могу опубликовать какой-нибудь актуальный код позже, если кому-то будет интересно.

Редактировать: Вероятно, это конкурентная черта во мне, но, увидев пост @Alsciende, я не удержался от публикации обещанного кода.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<html>
<head>
<title>8 unique random number between 1 and 100</title>
<script type="text/javascript" language="Javascript">
    function pick(n, min, max){
        var values = [], i = max;
        while(i >= min) values.push(i--);
        var results = [];
        var maxIndex = max;
        for(i=1; i <= n; i++){
            maxIndex--;
            var index = Math.floor(maxIndex * Math.random());
            results.push(values[index]);
            values[index] = values[maxIndex];
        }
        return results;
    }
    function go(){
        var running = true;
        do{
            if(!confirm(pick(8, 1, 100).sort(function(a,b){return a - b;}))){
                running = false;
            }
        }while(running)
    }
</script>
</head>

<body>
    <h1>8 unique random number between 1 and 100</h1>
    <p><button onclick="go()">Click me</button> to start generating numbers.</p>
    <p>When the numbers appear, click OK to generate another set, or Cancel to stop.</p>
</body>

6 голосов
/ 02 июня 2018

Современное решение JS с использованием Набор (и средний регистр O (n))

const nums = new Set();
while(nums.size !== 8) {
  nums.add(Math.floor(Math.random() * 100) + 1);
}

console.log([...nums]);
3 голосов
/ 13 апреля 2015

Это очень общая функция, которую я написал для генерации случайных уникальных / неуникальных целых чисел для массива. Предположим, что последний параметр является истинным в этом сценарии для этого ответа.

/* Creates an array of random integers between the range specified 
     len = length of the array you want to generate
     min = min value you require
     max = max value you require
     unique = whether you want unique or not (assume 'true' for this answer)
*/
    function _arrayRandom(len, min, max, unique) {
        var len = (len) ? len : 10,
                min = (min !== undefined) ? min : 1,
                max = (max !== undefined) ? max : 100,
                unique = (unique) ? unique : false,
                toReturn = [], tempObj = {}, i = 0;

        if(unique === true) {
            for(; i < len; i++) {
                var randomInt = Math.floor(Math.random() * ((max - min) + min));
                if(tempObj['key_'+ randomInt] === undefined) {
                    tempObj['key_'+ randomInt] = randomInt;
                    toReturn.push(randomInt);
                } else {
                    i--;
                }
            }
        } else {
            for(; i < len; i++) {
                toReturn.push(Math.floor(Math.random() * ((max - min) + min)));
            }
        }

        return toReturn;
    }

Здесь 'tempObj' - очень полезный объект, так как каждое сгенерированное случайное число будет напрямую проверять этот tempObj, если этот ключ уже существует, если нет, то мы уменьшаем i на единицу, так как нам требуется 1 дополнительный прогон с момента текущего номер уже существует.

В вашем случае выполните следующее

_arrayRandom(8, 1, 100, true);

Вот и все.

3 голосов
/ 04 марта 2010

Я бы сделал это:

function randomInt(min, max) {
    return Math.round(min + Math.random()*(max-min));
}
var index = {}, numbers = [];
for (var i=0; i<8; ++i) {
    var number;
    do {
        number = randomInt(1, 100);
    } while (index.hasOwnProperty("_"+number));
    index["_"+number] = true;
    numbers.push(number);
}
delete index;
2 голосов
/ 04 марта 2010

Перемешивание чисел от 1 до 100 - правильная базовая стратегия, но если вам нужно только 8 перемешанных чисел, нет необходимости перемешивать все 100 чисел.

Я не очень хорошо знаю Javascript, но считаю, что легко быстро создать массив из 100 нулей. Затем в течение 8 раундов вы меняете n-й элемент массива (n начинается с 0) на случайно выбранный элемент от n + 1 до 99. Конечно, любые элементы, которые еще не заполнены, означают, что этот элемент действительно был бы исходный индекс плюс 1, так что это тривиально для учета. Когда вы закончите с 8 раундами, первые 8 элементов вашего массива будут иметь ваши 8 перемешанных чисел.

1 голос
/ 04 ноября 2012

для массивов с такими отверстиями [,2,,4,,6,7,,] потому что моей проблемой было заполнить эти дыры. Поэтому я изменил его в соответствии с моими потребностями:)

у меня работало следующее модифицированное решение:)

var arr = [,2,,4,,6,7,,]; //example
while(arr.length < 9){
  var randomnumber=Math.floor(Math.random()*9+1);
  var found=false;
  for(var i=0;i<arr.length;i++){
    if(arr[i]==randomnumber){found=true;break;}
  }

  if(!found)
    for(k=0;k<9;k++)
    {if(!arr[k]) //if it's empty  !!MODIFICATION
      {arr[k]=randomnumber; break;}}
}

alert(arr); //outputs on the screen
...