Wie kann ich mit JavaScript eindeutige Zufallszahlen zwischen 1 und 100 generieren ?
Wie kann ich mit JavaScript eindeutige Zufallszahlen zwischen 1 und 100 generieren ?
Antworten:
Beispiel: Um 8 eindeutige Zufallszahlen zu generieren und in einem Array zu speichern, gehen Sie einfach wie folgt vor:
var arr = [];
while(arr.length < 8){
var r = Math.floor(Math.random() * 100) + 1;
if(arr.indexOf(r) === -1) arr.push(r);
}
console.log(arr);
Returns a random number between 0 (inclusive) and 1 (exclusive)
. Wenn the Math.random()
versehentlich 0 zurückgegeben wird, Math.ceil(0)
ist dies ebenfalls 0, obwohl die Chance gering ist.
randlines file | head -10
.
Generieren Sie eine Permutation von 100 Zahlen und wählen Sie dann seriell.
Verwenden Sie den Knuth Shuffle-Algorithmus (auch bekannt als 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;
}
}
EDIT :
Verbesserter Code:
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);
}
Potenzielles Problem:
Angenommen, wir haben ein Array von 100 Zahlen {zB [1,2,3 ... 100]} und hören nach 8 Swaps auf zu tauschen. dann sieht das Array meistens wie folgt aus: {1,2,3,76,5,6,7,8, ... Zahlen hier werden gemischt ... 10}.
Weil jede Zahl mit einer Wahrscheinlichkeit von 1/100 getauscht wird, ist es wahrscheinlich. des Austauschs der ersten 8 Zahlen ist 8/100, während prob. der Austausch anderer 92 ist 92/100.
Wenn wir jedoch einen Algorithmus für ein vollständiges Array ausführen, sind wir sicher, dass (fast) jeder Eintrag ausgetauscht wird.
Ansonsten stehen wir vor der Frage: Welche 8 Zahlen sollen wir wählen?
Moderne JS-Lösung mit Set (und Durchschnittsfall O (n))
const nums = new Set();
while(nums.size !== 8) {
nums.add(Math.floor(Math.random() * 100) + 1);
}
console.log([...nums]);
Math.floor(Math.random()*100) + 1
Set
in JS zu entdecken ! Würde diese Lösung jedoch nicht zu einer unnötigen Generierung von Zahlen führen, bis man die Anforderung der Eindeutigkeit erfüllt, insbesondere in den letzten Iterationen, wenn 8 näher an 100 liegt? Daher denke ich, ich bevorzuge die auch elegante Antwort mit sort
unten.
Die oben genannten Techniken sind gut, wenn Sie eine Bibliothek vermeiden möchten. Abhängig davon, ob Sie mit einer Bibliothek einverstanden sind, würde ich empfehlen, die Möglichkeit zum Generieren von zufälligen Inhalten in JavaScript zu prüfen .
Speziell um Ihre Frage zu lösen, ist es mit Chance so einfach wie:
// 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>
Haftungsausschluss, als Autor von Chance bin ich etwas voreingenommen;)
var codes = chance.unique(chance.string, 8)
Wenn Sie die Codes aus einem bestimmten Zeichenpool chance.unique(chance.string, 8, {pool: "abcd1234"})
abrufen möchten, können Sie dies wie folgt angeben: wobei abcd1234 beliebige Zeichen im Pool sein können. Siehe Chancejs.com/#string
chance.string({ length: 8 })
und wenn Sie nur möchten, dass bestimmte Zeichen in dieser Zeichenfolge erscheinen, chance.string({ pool: 'abcd1234', length: 8 })
die eine zufällige 8-Zeichen-Zeichenfolge aus den Zeichen abcd1234 zurückgeben, also zum Beispiel "2c2c44bc" oder "331141cc"
Um lange und unzuverlässige Mischvorgänge zu vermeiden, würde ich Folgendes tun ...
Voila - keine wiederholten Zahlen.
Ich kann später einen aktuellen Code veröffentlichen, wenn jemand interessiert ist.
Bearbeiten: Es ist wahrscheinlich die Konkurrenzserie in mir, aber nachdem ich den Beitrag von @Alsciende gesehen habe, konnte ich nicht widerstehen, den versprochenen Code zu veröffentlichen.
<!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>
Ein anderer Ansatz besteht darin, ein Array mit 100 Elementen mit aufsteigenden Zahlen zu generieren und es zufällig zu sortieren. Dies führt tatsächlich zu einem wirklich kurzen und (meiner Meinung nach) einfachen Ausschnitt.
const numbers = Array(100).fill().map((_, index) => index + 1);
numbers.sort(() => Math.random() - 0.5);
console.log(numbers.slice(0, 8));
sort
ist gut implementiert, was ich sicher bin).
Ich würde das tun:
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;
Dies ist eine sehr generische Funktion, die ich geschrieben habe, um zufällige eindeutige / nicht eindeutige Ganzzahlen für ein Array zu generieren. Angenommen, der letzte Parameter ist in diesem Szenario für diese Antwort wahr.
/* 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;
}
Hier ist das 'tempObj' ein sehr nützliches Objekt, da jede generierte Zufallszahl dieses tempObj direkt eincheckt, wenn dieser Schlüssel bereits vorhanden ist. Wenn nicht, reduzieren wir das i um eins, da wir 1 zusätzlichen Lauf benötigen, da die aktuelle Zufallszahl bereits vorhanden ist .
Führen Sie in Ihrem Fall Folgendes aus
_arrayRandom(8, 1, 100, true);
Das ist alles.
min = (min) ? min : 1,
gibt immer 1 zurück (daher wird 0 niemals ausgewählt)
Das Mischen der Zahlen von 1 auf 100 ist die richtige Grundstrategie. Wenn Sie jedoch nur 8 gemischte Zahlen benötigen, müssen Sie nicht alle 100 Zahlen mischen.
Ich kenne Javascript nicht sehr gut, aber ich glaube, es ist einfach, schnell ein Array von 100 Nullen zu erstellen. Dann tauschen Sie für 8 Runden das n-te Element des Arrays (n beginnend bei 0) gegen ein zufällig ausgewähltes Element von n + 1 bis 99. Natürlich bedeuten alle Elemente, die noch nicht ausgefüllt sind, dass das Element wirklich gewesen wäre Der ursprüngliche Index plus 1, das ist also trivial zu berücksichtigen. Wenn Sie mit den 8 Runden fertig sind, haben die ersten 8 Elemente Ihres Arrays Ihre 8 gemischten Zahlen.
Gleicher Permutationsalgorithmus wie The Machine Charmer, jedoch mit einer prototypisierten Implementierung. Besser geeignet für eine große Anzahl von Picks. Verwendet die Destrukturierungszuweisung js 1.7, falls verfügbar.
// 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);
Bearbeiten: Ein anderer Vorschlag, der besser für eine kleine Anzahl von Picks geeignet ist, basierend auf Belugabobs Antwort. Um die Eindeutigkeit zu gewährleisten, entfernen wir die ausgewählten Zahlen aus dem Array.
// 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);
für Arrays mit [,2,,4,,6,7,,]
solchen Löchern, weil mein Problem darin bestand, diese Löcher zu füllen. Also habe ich es nach meinen Wünschen modifiziert :)
Die folgende modifizierte Lösung hat bei mir funktioniert :)
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
Die beste frühere Antwort ist die Antwort von sje397
. Sie erhalten so schnell wie möglich so gute Zufallszahlen wie möglich.
Meine Lösung ist seiner Lösung sehr ähnlich. Manchmal möchten Sie jedoch die Zufallszahlen in zufälliger Reihenfolge, und deshalb habe ich beschlossen, eine Antwort zu posten. Darüber hinaus biete ich eine allgemeine Funktion.
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));
Hier ist meine ES6-Version, die ich zusammengeschustert habe. Ich bin sicher, es kann etwas konsolidierter sein.
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);
Wie wäre es mit der Verwendung von Objekteigenschaften als Hash-Tabelle ? Auf diese Weise besteht Ihr bestes Szenario darin, nur 8 Mal zufällig zu wählen. Es wäre nur dann effektiv, wenn Sie einen kleinen Teil des Zahlenbereichs möchten. Es ist auch viel weniger speicherintensiv als Fisher-Yates, da Sie keinen Speicherplatz für ein Array zuweisen müssen.
var ht={}, i=rands=8;
while ( i>0 || keys(ht).length<rands) ht[Math.ceil(Math.random()*100)]=i--;
alert(keys(ht));
Ich habe dann herausgefunden, dass Object.keys (obj) eine ECMAScript 5-Funktion ist, so dass das oben Genannte im Internet im Moment so gut wie nutzlos ist. Fürchte dich nicht, denn ich habe es ECMAScript 3-kompatibel gemacht, indem ich eine Tastenfunktion wie diese hinzugefügt habe.
if (typeof keys == "undefined")
{
var keys = function(obj)
{
props=[];
for (k in ht) if (ht.hasOwnProperty(k)) props.push(k);
return props;
}
}
Wenn Sie mehr eindeutige benötigen, müssen Sie ein Array (1..100) generieren.
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;
}
Der obige Code ist schneller:
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]
Hinzufügen einer weiteren besseren Version desselben Codes (akzeptierte Antwort) mit der JavaScript 1.6 indexOf-Funktion. Sie müssen nicht jedes Mal, wenn Sie das Duplikat überprüfen, das gesamte Array durchlaufen.
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;
}
Ältere Versionen von Javascript können weiterhin die Version oben verwenden
PS: Ich habe versucht, ein Update für das Wiki vorzuschlagen, aber es wurde abgelehnt. Ich denke immer noch, dass es für andere nützlich sein kann.
Dies ist meine persönliche Lösung:
<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>
Es werden zufällig 8 eindeutige Array-Werte (zwischen 0 und 7) generiert und anschließend mithilfe eines Warnfelds angezeigt.
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;
}
Ich denke, diese Methode unterscheidet sich von den in den meisten Antworten angegebenen Methoden, daher dachte ich, ich könnte hier eine Antwort hinzufügen (obwohl die Frage vor 4 Jahren gestellt wurde).
Wir generieren 100 Zufallszahlen und markieren jede mit Zahlen von 1 bis 100. Dann sortieren wir diese markierten Zufallszahlen und die Tags werden zufällig gemischt. Alternativ könnte man, wie in dieser Frage benötigt, darauf verzichten, nur die Top 8 der markierten Zufallszahlen zu finden. Das Finden der Top-8-Elemente ist billiger als das Sortieren des gesamten Arrays.
Hierbei ist zu beachten, dass der Sortieralgorithmus diesen Algorithmus beeinflusst. Wenn der verwendete Sortieralgorithmus stabil ist, besteht eine leichte Verzerrung zugunsten kleinerer Zahlen. Idealerweise möchten wir, dass der Sortieralgorithmus instabil und nicht einmal auf Stabilität (oder Instabilität) ausgerichtet ist, um eine Antwort mit perfekt gleichmäßiger Wahrscheinlichkeitsverteilung zu erhalten.
Dies kann die Erzeugung von bis zu 20-stelligen EINZIGARTIGEN Zufallszahlen verarbeiten
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);
Diese Lösung verwendet den Hash, der viel leistungsfähiger ist als die Überprüfung, ob sich der Hash im Array befindet. Es hat auch extra sichere Kontrollen. Ich hoffe es hilft.
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))
Die Implementierung als Generator macht es ziemlich schön, damit zu arbeiten. Beachten Sie, dass sich diese Implementierung von denen unterscheidet, bei denen das gesamte Eingabearray zuerst gemischt werden muss.
Diese
sample
Funktion arbeitet träge und gibt Ihnen 1 zufälliges Element pro Iteration bis zu denN
gewünschten Elementen. Das ist schön, denn wenn Sie nur 3 Elemente aus einer Liste von 1000 möchten , müssen Sie nicht alle 1000 Elemente zuerst berühren.
// 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]
Ich habe mich für eine Implementierung entschieden, die sample
das Eingabearray nicht mutiert, aber Sie könnten leicht argumentieren, dass eine mutierende Implementierung günstig ist.
Beispielsweise shuffle
möchte die Funktion möglicherweise das ursprüngliche Eingabearray mutieren. Oder Sie möchten zu verschiedenen Zeiten von derselben Eingabe abtasten und die Eingabe jedes Mal aktualisieren.
// sample :: Integer -> [a] -> [a]
const sample = n => function* (xs) {
let len = xs.length;
while (n > 0 && len > 0) {
let i = (Math.random() * len) >> 0;
yield xs.splice(i,1)[0];
n--; len--;
}
}
// deal :: [Card] -> [Card]
const deal = xs => Array.from(sample (2) (xs));
// setup a deck of cards (13 in this case)
// cards :: [Card]
let cards = 'A234567890JQK'.split('');
// deal 6 players 2 cards each
// players :: [[Card]]
let players = Array.from(Array(6), $=> deal(cards))
console.log(players);
// [K, J], [6, 0], [2, 8], [Q, 7], [5, 4], [9, A]
// `cards` has been mutated. only 1 card remains in the deck
console.log(cards);
// [3]
sample
ist aufgrund der Array-Eingangsmutation keine reine Funktion mehr , kann aber unter bestimmten Umständen (siehe oben) sinnvoller sein.
Ein weiterer Grund, warum ich einen Generator anstelle einer Funktion gewählt habe, die nur ein Array zurückgibt, ist, dass Sie die Abtastung möglicherweise bis zu einer bestimmten Bedingung fortsetzen möchten.
Vielleicht möchte ich die erste Primzahl aus einer Liste von 1.000.000 Zufallszahlen.
Da wir mit einem Generator arbeiten, ist diese Aufgabe trivial
const randomPrimeNumber = listOfNumbers => {
for (let x of sample(Infinity) (listOfNumbers)) {
if (isPrime(x))
return x;
}
return NaN;
}
Dadurch wird kontinuierlich jeweils 1 Zufallszahl abgetastet. x
Überprüfen Sie, ob es sich um eine Primzahl handelt, und kehren x
Sie dann zurück, wenn dies der Fall ist. Wenn die Liste der Zahlen erschöpft ist, bevor eine Primzahl gefunden wird, NaN
wird sie zurückgegeben.
Hinweis:
Diese Antwort wurde ursprünglich auf eine andere Frage übertragen, die als Duplikat dieser Frage geschlossen wurde. Da es sich stark von den anderen hier angebotenen Lösungen unterscheidet, habe ich beschlossen, es auch hier zu teilen
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
}
Die Verwendung von a Set
ist Ihre schnellste Option. Hier ist eine generische Funktion zum Abrufen eines eindeutigen Zufalls, der einen Rückrufgenerator verwendet. Jetzt ist es schnell und wiederverwendbar .
// 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))
Dies ist eine Implementierung von Fisher Yates / Durstenfeld Shuffle , jedoch ohne tatsächliche Erstellung eines Arrays, wodurch die Platzkomplexität oder der benötigte Speicher reduziert werden, wenn die Vergleich zur Anzahl der verfügbaren Elemente klein ist.
Um 8 von 100 Zahlen auszuwählen, muss kein Array mit 100 Elementen erstellt werden.
Angenommen, ein Array wird erstellt.
rnd
) von 1 bis 100 rnd
Wenn kein Array erstellt wird, kann eine HashMap verwendet werden, um die tatsächlich getauschten Positionen zu speichern. Wenn die zweite generierte Zufallszahl gleich der zuvor generierten Zahl ist, liefert die Karte den aktuellen Wert an dieser Position anstelle des tatsächlichen Werts.
const getRandom_ = (start, end) => {
return Math.floor(Math.random() * (end - start + 1)) + start;
};
const getRealValue_ = (map, rnd) => {
if (map.has(rnd)) {
return getRealValue_(map, map.get(rnd));
} else {
return rnd;
}
};
const getRandomNumbers = (n, start, end) => {
const out = new Map();
while (n--) {
const rnd = getRandom_(start, end--);
out.set(getRealValue_(out, rnd), end + 1);
}
return [...out.keys()];
};
console.info(getRandomNumbers(8, 1, 100));
console.info(getRandomNumbers(8, 1, Math.pow(10, 12)));
console.info(getRandomNumbers(800000, 1, Math.pow(10, 15)));
Hier ist ein Beispiel für zufällige 5 Zahlen aus einem Bereich von 0 bis 100 (sowohl 0 als auch 100 enthalten) ohne Duplizierung.
let finals = [];
const count = 5; // Considering 5 numbers
const max = 100;
for(let i = 0; i < max; i++){
const rand = Math.round(Math.random() * max);
!finals.includes(rand) && finals.push(rand)
}
finals = finals.slice(0, count)
Sie können dies auch mit einem Einzeiler wie diesem tun:
[...((add, set) => add(set, add))((set, add) => set.size < 8 ? add(set.add(Math.floor(Math.random()*100) + 1), add) : set, new Set())]