Как я могу сгенерировать некоторые уникальные случайные числа от 1 до 100, используя JavaScript?
Создание уникальных случайных чисел от 1 до 100
Ответ 1
Например: чтобы сгенерировать 8 уникальных случайных чисел и сохранить их в массиве, вы можете просто сделать это:
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);
Ответ 2
- Залить массив с номерами от 1 до 100.
- Перемешать его.
- Возьмите первые 8 элементов результирующего массива.
Ответ 3
Сгенерируйте перестановку из 100 чисел, а затем выберите последовательно.
Использовать Knuth Shuffle (так называемый алгоритм Fisher-Yates shuffle).
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;
}
}
ИЗМЕНИТЬ
Улучшенный код:
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 номеров выбрать?
Ответ 4
Вышеупомянутые методы хороши, если вы хотите избежать библиотеки, но в зависимости от того, будет ли у вас все в порядке с библиотекой, я предлагаю проверить Chance для генерируя случайные вещи в 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>
Ответ 5
Чтобы избежать длительных и ненадежных тасов, я бы сделал следующее...
- Создайте массив, содержащий число от 1 до 100, в порядке.
- Создание случайного числа между 1 и 100
- Посмотрите номер в этом индексе в массиве и сохраните в своих результатах.
- Удалите элемент из массива, сделав его короче
- Повторяйте с шага 2, но используйте 99 как верхний предел случайного числа
- Повторите шаг 2, но используйте 98 как верхний предел случайного числа
- Повторите шаг 2, но используйте 97 как верхний предел случайного числа
- Повторите шаг 2, но используйте 96 как верхний предел случайного числа
- Повторите шаг 2, но используйте 95 как верхний предел случайного числа
- Повторяйте с шага 2, но используйте 94 как верхний предел случайного числа
- Повторите шаг 2, но используйте 93 как верхний предел случайного числа
Voila - нет повторных номеров.
Я могу опубликовать некоторый фактический код позже, если кто-то заинтересован.
Редактировать: это, вероятно, конкурентная полоса во мне, но, увидев сообщение от @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
Современное решение JS с использованием Set (и среднего случая O (n))
const nums = new Set();
while(nums.size !== 8) {
nums.add(Math.floor(Math.random() * 100) + 1);
}
console.log([...nums]);
Ответ 7
Я бы сделал это:
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;
Ответ 8
Это очень общая функция, которую я написал для генерации случайных уникальных/неистинных целых чисел для массива. Предположим, что для этого ответа последний параметр должен быть истинным в этом сценарии.
/* 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" - очень полезный obj, поскольку каждое генерируемое случайное число будет напрямую проверять этот tempObj, если этот ключ уже существует, если нет, то мы уменьшаем я на единицу, так как нам нужен еще один дополнительный запуск, поскольку текущий случайный номер уже существует.
В вашем случае запустите следующие
_arrayRandom(8, 1, 100, true);
Что все.
Ответ 9
Перемешивание чисел от 1 до 100 является правильной базовой стратегией, но если вам нужно всего 8 перетасованных чисел, нет необходимости перетасовывать все 100 номеров.
Я не знаю Javascript очень хорошо, но я считаю, что легко создать массив из 100 нулей быстро. Затем в течение 8 раундов вы меняете n-й элемент массива (n начиная с 0) со случайно выбранным элементом от n + 1 до 99. Конечно, любые элементы, которые не заполнены, еще не означают, что элемент действительно был бы исходный индекс плюс 1, так что тривиальный фактор. Когда вы закончите с 8 раундами, первые 8 элементов вашего массива будут иметь ваши 8 перетасованных чисел.
Ответ 10
Другой более простой подход - создать массив из 100 элементов с возрастающими числами и отсортировать его случайным образом. На самом деле это приводит к очень короткому и (на мой взгляд) простому фрагменту.
const numbers = [ ...Array(100).keys() ].map(num => num + 1);
numbers.sort(() => Math.random() - 0.5);
console.log(numbers.slice(0, 8));
Ответ 11
Такой же алгоритм перестановок, как и Charmer Machine, но с прототипированной реализацией. Лучше подходит для большого количества выборков. Использует js 1.7 destructuring назначение, если доступно.
// swaps elements at index i and j in array this
// swapping is easy on js 1.7 (feature detection)
Array.prototype.swap = (function () {
var i=0, j=1;
try { [i,j]=[j,i]; }
catch (e) {}
if(i) {
return function(i,j) {
[this[i],this[j]] = [this[j],this[i]];
return this;
}
} else {
return function(i,j) {
var temp = this[i];
this[i] = this[j];
this[j] = temp;
return this;
}
}
})();
// shuffles array this
Array.prototype.shuffle = function() {
for(var i=this.length; i>1; i--) {
this.swap(i-1, Math.floor(i*Math.random()));
}
return this;
}
// returns n unique random numbers between min and max
function pick(n, min, max) {
var a = [], i = max;
while(i >= min) a.push(i--);
return a.shuffle().slice(0,n);
}
pick(8,1,100);
Изменить: Другое предложение, более подходящее для небольшого количества выборов, основано на ответе белугабоба. Чтобы гарантировать уникальность, мы удаляем выбранные числа из массива.
// removes n random elements from array this
// and returns them
Array.prototype.pick = function(n) {
if(!n || !this.length) return [];
var i = Math.floor(this.length*Math.random());
return this.splice(i,1).concat(this.pick(n-1));
}
// returns n unique random numbers between min and max
function pick(n, min, max) {
var a = [], i = max;
while(i >= min) a.push(i--);
return a.pick(n);
}
pick(8,1,100);
Ответ 12
для массивов с отверстиями типа [,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 empty !!MODIFICATION
{arr[k]=randomnumber; break;}}
}
alert(arr); //outputs on the screen
Ответ 13
Самый лучший ответ - ответ sje397
. Вы получите как можно более хорошие случайные числа, как можно быстрее.
Мое решение очень похоже на его решение. Однако иногда вам нужны случайные числа в случайном порядке, и именно поэтому я решил опубликовать ответ. Кроме того, я предоставляю общую функцию.
function selectKOutOfN(k, n) {
if (k>n) throw "k>n";
var selection = [];
var sorted = [];
for (var i = 0; i < k; i++) {
var rand = Math.floor(Math.random()*(n - i));
for (var j = 0; j < i; j++) {
if (sorted[j]<=rand)
rand++;
else
break;
}
selection.push(rand);
sorted.splice(j, 0, rand);
}
return selection;
}
alert(selectKOutOfN(8, 100));
Ответ 14
var arr = []
while(arr.length < 8){
var randomnumber=Math.ceil(Math.random()*100)
if(arr.indexOf(randomnumber) === -1){arr.push(randomnumber)}
}
document.write(arr);
короче, чем другие ответы, которые я видел
Ответ 15
Как насчет использования свойств объекта как хеш-таблицы? Таким образом, ваш лучший сценарий состоит только в случайном 8 раз. Это было бы эффективно только в том случае, если вы хотите получить небольшую часть диапазона чисел. Это также значительно меньше памяти, чем Fisher-Yates, потому что вам не нужно выделять пространство для массива.
var ht={}, i=rands=8;
while ( i>0 || keys(ht).length<rands) ht[Math.ceil(Math.random()*100)]=i--;
alert(keys(ht));
Затем я узнал, что Object.keys(obj) - это функция ECMAScript 5, поэтому вышеизложенное практически бесполезно в интернетах Теперь. Не бойтесь, потому что я сделал его совместимым с ECMAScript 3, добавив такие функции клавиш, как это.
if (typeof keys == "undefined")
{
var keys = function(obj)
{
props=[];
for (k in ht) if (ht.hasOwnProperty(k)) props.push(k);
return props;
}
}
Ответ 16
var bombout=0;
var checkArr=[];
var arr=[];
while(arr.length < 8 && bombout<100){
bombout++;
var randomNumber=Math.ceil(Math.random()*100);
if(typeof checkArr[randomNumber] == "undefined"){
checkArr[randomNumber]=1;
arr.push(randomNumber);
}
}
// untested - hence bombout
Ответ 17
если вам нужно больше уникального, вы должны сгенерировать массив (1..100).
var arr=[];
function generateRandoms(){
for(var i=1;i<=100;i++) arr.push(i);
}
function extractUniqueRandom()
{
if (arr.length==0) generateRandoms();
var randIndex=Math.floor(arr.length*Math.random());
var result=arr[randIndex];
arr.splice(randIndex,1);
return result;
}
function extractUniqueRandomArray(n)
{
var resultArr=[];
for(var i=0;i<n;i++) resultArr.push(extractUniqueRandom());
return resultArr;
}
выше код быстрее:
extractUniqueRandomArray (50) = > [2, 79, 38, 59, 63, 42, 52, 22, 78, 50, 39, 77, 1, 88, 40, 23, 48, 84, 91, 49, 4, 54, 93, 36, 100, 82, 62, 41, 89, 12, 24, 31, 86, 92, 64, 75, 70, 61, 67, 98, 76, 80, 56, 90, 83, 44, 43, 47, 7, 53 ]
Ответ 18
Добавление другой лучшей версии того же кода (принятый ответ) с функцией JavaScript 1.6 indexOf. Не нужно перебирать весь массив каждый раз, когда вы проверяете дубликат.
var arr = []
while(arr.length < 8){
var randomnumber=Math.ceil(Math.random()*100)
var found=false;
if(arr.indexOf(randomnumber) > -1){found=true;}
if(!found)arr[arr.length]=randomnumber;
}
Старая версия Javascript по-прежнему может использовать версию вверху
PS: Пробовал предлагать обновление для wiki, но оно было отклонено. Я все еще думаю, что это может быть полезно для других.
Ответ 19
Это мое личное решение:
<script>
var i, k;
var numbers = new Array();
k = Math.floor((Math.random()*8));
numbers[0]=k;
for (var j=1;j<8;j++){
k = Math.floor((Math.random()*8));
i=0;
while (i < numbers.length){
if (numbers[i] == k){
k = Math.floor((Math.random()*8));
i=0;
}else {i++;}
}
numbers[j]=k;
}
for (var j=0;j<8;j++){
alert (numbers[j]);
}
</script>
Он случайным образом генерирует 8 уникальных значений массива (от 0 до 7), а затем отображает их с помощью окна предупреждения.
Ответ 20
function getUniqueRandomNos() {
var indexedArrayOfRandomNo = [];
for (var i = 0; i < 100; i++) {
var randNo = Math.random();
indexedArrayOfRandomNo.push([i, randNo]);
}
indexedArrayOfRandomNo.sort(function (arr1, arr2) {
return arr1[1] - arr2[1]
});
var uniqueRandNoArray = [];
for (i = 0; i < 8; i++) {
uniqueRandNoArray.push(indexedArrayOfRandomNo[i][0]);
}
return uniqueRandNoArray;
}
Я думаю, что этот метод отличается от методов, приведенных в большинстве ответов, поэтому я подумал, что могу добавить здесь ответ (хотя вопрос был задан 4 года назад).
Мы генерируем 100 случайных чисел и помечаем каждый из них цифрами от 1 до 100. Затем мы сортируем эти помеченные случайные числа, и теги случайно перетасовываются. В качестве альтернативы, по мере необходимости в этом вопросе, можно было бы покончить с тем, чтобы найти только 8 из отмеченных случайных чисел. Поиск 8 лучших предметов дешевле, чем сортировка всего массива.
Здесь следует отметить, что алгоритм сортировки влияет на этот алгоритм. Если используемый алгоритм сортировки является стабильным, есть небольшое смещение в пользу меньших чисел. В идеале мы хотели бы, чтобы алгоритм сортировки был неустойчивым и даже не предвзятым к стабильности (или нестабильности) для получения ответа с абсолютно равномерным распределением вероятности.
Ответ 21
Это может обрабатывать генерирование до 20 цифр UNIQUE случайных чисел
JS
var generatedNumbers = [];
function generateRandomNumber(precision) { // input --> number precision in integer
if (precision <= 20) {
var randomNum = Math.round(Math.random().toFixed(precision) * Math.pow(10, precision));
if (generatedNumbers.indexOf(randomNum) > -1) {
if (generatedNumbers.length == Math.pow(10, precision))
return "Generated all values with this precision";
return generateRandomNumber(precision);
} else {
generatedNumbers.push(randomNum);
return randomNum;
}
} else
return "Number Precision shoould not exceed 20";
}
generateRandomNumber(1);
Ответ 22
Это решение использует хэш, который намного более эффективен O (1), чем проверка того, находится ли он в массиве. Он также имеет дополнительные безопасные проверки. Надеюсь, что это поможет.
function uniqueArray(minRange, maxRange, arrayLength) {
var arrayLength = (arrayLength) ? arrayLength : 10
var minRange = (minRange !== undefined) ? minRange : 1
var maxRange = (maxRange !== undefined) ? maxRange : 100
var numberOfItemsInArray = 0
var hash = {}
var array = []
if ( arrayLength > (maxRange - minRange) ) throw new Error('Cannot generate unique array: Array length too high')
while(numberOfItemsInArray < arrayLength){
// var randomNumber = Math.floor(Math.random() * (maxRange - minRange + 1) + minRange)
// following line used for performance benefits
var randomNumber = (Math.random() * (maxRange - minRange + 1) + minRange) << 0
if (!hash[randomNumber]) {
hash[randomNumber] = true
array.push(randomNumber)
numberOfItemsInArray++
}
}
return array
}
document.write(uniqueArray(1, 100, 8))
Ответ 23
Реализация этого как генератора делает его довольно приятным для работы. Обратите внимание: эта реализация отличается от той, которая требует, чтобы весь входной массив сначала перетасовался.
Эта функция
sample
работает лениво, предоставляя вам 1 случайный элемент за итерацию доN
элементов, которые вы запрашиваете. Это хорошо, потому что, если вы просто хотите, чтобы элементы 3 из списка 1000, вам не нужно касаться всего 1000 элементов.
// sample :: Integer -> [a] -> [a]
const sample = n => function* (xs) {
let ys = xs.slice(0);
let len = xs.length;
while (n > 0 && len > 0) {
let i = (Math.random() * len) >> 0;
yield ys.splice(i,1)[0];
n--; len--;
}
}
// example inputs
let items = ['a', 'b', 'c', 'd', 'e', 'f', 'g'];
let numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
// get 3 random items
for (let i of sample(3) (items))
console.log(i); // f g c
// partial application
const lotto = sample(3);
for (let i of lotto(numbers))
console.log(i); // 3 8 7
// shuffle an array
const shuffle = xs => Array.from(sample (Infinity) (xs))
console.log(shuffle(items)) // [b c g f d e a]
Ответ 24
getRandom (min, max) {
return Math.floor(Math.random() * (max - min)) + min
}
getNRandom (min, max, n) {
const numbers = []
if (min > max) {
return new Error('Max is gt min')
}
if (min === max) {
return [min]
}
if ((max - min) >= n) {
while (numbers.length < n) {
let rand = this.getRandom(min, max + 1)
if (numbers.indexOf(rand) === -1) {
numbers.push(rand)
}
}
}
if ((max - min) < n) {
for (let i = min; i <= max; i++) {
numbers.push(i)
}
}
return numbers
}
Ответ 25
Использование Set
- ваш самый быстрый вариант. Вот общая функция для получения уникального случайного, использующего генератор обратного вызова. Теперь он быстрый и многоразовый.
// Get a unique 'anything'
let unique = new Set()
function getUnique(generator) {
let number = generator()
while (!unique.add(number)) {
number = generator()
}
return number;
}
// The generator. Return anything, not just numbers.
const between_1_100 = () => 1 + Math.floor(Math.random() * 100)
// Test it
for (var i = 0; i < 8; i++) {
const aNumber = getUnique(between_1_100)
}
// Dump the 'stored numbers'
console.log(Array.from(unique))
Ответ 26
Вот моя версия ES6, которую я собрал вместе. Я уверен, что это может быть немного более консолидированным.
function randomArray(i, min, max) {
min = Math.ceil(min);
max = Math.floor(max);
let arr = Array.from({length: i}, () => Math.floor(Math.random()* (max - min)) + min);
return arr.sort();
}
let uniqueItems = [...new Set(randomArray(8, 0, 100))]
console.log(uniqueItems);
Ответ 27
Вы также можете сделать это с помощью одного лайнера:
[...((add, set) => add(set, add))((set, add) => set.size < 8 ? add(set.add(Math.floor(Math.random()*100) + 1), add) : set, new Set())]