Generieren Sie eindeutige Zufallszahlen zwischen 1 und 100


98

Wie kann ich mit JavaScript eindeutige Zufallszahlen zwischen 1 und 100 generieren ?


18
Nicht wirklich ein Betrüger, da es sich um Javascript handelt.
Dotty

2
@dotty Nun, es gibt keinen wesentlichen Unterschied zwischen Javascript und einer anderen Sprache, aber ich werde nicht dafür stimmen, zu schließen.
Pointy

1
Ich werde auch nicht dafür stimmen, zu schließen. Das ist spezifisch genug.
Josh Stodola


1
Es gibt einen anderen saubereren Weg, um dies zu tun stackoverflow.com/questions/51898200/…
Huangism

Antworten:


171

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);


15
Tatsächlicher Code ist für solche Fragen so viel besser als Pseudocode;) (löschte meine Antwort, die Pseudocode war ...)
Roman Starkov

3
O kann gepflückt werden; benutze var randomnumber = Math.ceil (Math.random () * 100)
Alsciende

9
-1: Dieser Algorithmus ist der naive Ansatz. es ist sehr ineffizient.
Frerich Raabe

39
Beeindruckend. Naiv scheint ein bisschen stark. Es ist vielleicht nicht die beste Lösung, aber es ist einfach, kurz, leicht zu sehen, was los ist, und läuft innerhalb akzeptabler Betriebsparameter für das, was erreicht werden muss. Weiter zur nächsten Aufgabe. Perfektion ist großartig, aber "erledigt" ist besser als "perfekt".
Adam0101

4
Es besteht die Möglichkeit, dass die Funktion im Array eine 0 zurückgibt. Laut diesem Link: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… , Math.random () 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.
Qian Chen

43
  1. Füllen Sie ein Array mit den Zahlen 1 bis 100.
  2. Mische es .
  3. Nehmen Sie die ersten 8 Elemente des resultierenden Arrays.

8
Sicherlich ist es effizienter, den Code so zu optimieren, dass nur die ersten 8 Shuffles ausgeführt werden. (und dann nehmen Sie die letzten 8 Elemente des halb gemischten Arrays)
2.

1
So mache ich das auch immer. Wenn ich also zehn zufällige Zeilen aus einer Datei mit einer Reihe von Zeilen wollte, tue ich das randlines file | head -10.
Tchrist

1
Ich denke, es ist die richtige Antwort, weil es die Wahrscheinlichkeitsverteilung beibehält, die die akzeptierte Antwort nicht hat
Roberto Tomás

2
Was ist, wenn N = 10 ^ 12? Nicht sehr effizient.
Shinzou

2
@shinzou In der realen Welt würden Sie 10 ^ 12 Zahlen nicht mit JavaScript sortieren. Eine tirivalische Frage erfordert eine triviale Antwort. Ich bin nicht hier, um den Welthunger zu lösen. Dafür bin ich gut gerüstet, aber darum geht es bei der Frage nicht.
DegDwight

14

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;

   }
}

CODE VON LINK KOPIERT.

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?


5
Dieser Ansatz ist korrekt, aber nicht optimal: Sie können nach acht Swaps aufhören zu mischen, da Sie nur acht Zufallszahlen benötigen. Der obige Code tauscht das gesamte Array aus (in diesem Szenario 100 Elemente).
Frerich Raabe

Der Code könnte ernsthaft verbessert werden. Rückgabewerte, Nebenwirkungen und Funktionsnutzung sind IMO wirklich verschwommen. Wenn Sie mit Ihrer FisherYates-Funktion eine Funktion schreiben, die das ursprüngliche Problem genau beantwortet, ist dies möglicherweise klarer.
Alsciende

1
Antwort mit verbessertem Code aktualisiert. Auch @Frerich Raabe: Problem mit dem Anhalten nach acht Swaps wird erwähnt.
Pratik Deoghare

Ihr Fisher-Yates-Algorithmus ist falsch. r sollte von i abhängen. Siehe meine Antwort: stackoverflow.com/questions/2380019/…
Alsciende

Ups sorry mein schrecklicher Fehler !! Ihre Implementierung ist cool. Mochte es. +1. Bitte lassen Sie mich wissen, wenn etwas anderes nicht stimmt. Danke.
Pratik Deoghare

11

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]);


Warum ist es O (n)? Kann es nicht für eine beliebige Zeitschleife wiederholt werden?
Anthony Wieser

@AnthonyWieser Du hast recht, schlimmster Fall. Ich habe einen durchschnittlichen Fall angedeutet, da Set.add o (1)
Alister

Ich denke, dies könnte 0 zurückgeben, wie meine Antwort es gewohnt war, bevor sie geändert wurdeMath.floor(Math.random()*100) + 1
adam0101

Sehr cool Setin 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 sortunten.
Gilad Barner

10

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;)


Upvote, weil ich das Run-Code-Snippet noch nie gesehen habe
surfmuggle

Wie kann ich mit Chance.js einen Code (8 zufällige alphanumerische Zeichenfolgen) für Gutscheine erstellen, der eindeutig sein muss? Hinweis: Die Gutscheine werden auf Anfrage ausgestellt, daher ist die Anzahl der Codes unbegrenzt
Oscar Yuandinata

@OscarYuandinata das ist einfach, einfach tun 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
Victor Quinn

@ VictorQuinn, sorry ich habe mich nicht klar gemacht. Ich meine, der Gutscheincode besteht aus einer 8-stelligen zufälligen alphanumerischen Zeichenfolge, nicht aus einem Array von 8 zufälligen alphanumerischen Zeichenfolgen. hahaha ..
Oscar Yuandinata

Oh @OscarYuandinata, das ist viel einfacher, 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"
Victor Quinn,

8

Um lange und unzuverlässige Mischvorgänge zu vermeiden, würde ich Folgendes tun ...

  1. Generieren Sie nacheinander ein Array, das die Zahl zwischen 1 und 100 enthält.
  2. Generieren Sie eine Zufallszahl zwischen 1 und 100
  3. Suchen Sie die Nummer an diesem Index im Array und speichern Sie sie in Ihren Ergebnissen
  4. Entfernen Sie das Element aus dem Array, um es kürzer zu machen
  5. Wiederholen Sie ab Schritt 2, verwenden Sie jedoch 99 als Obergrenze für die Zufallszahl
  6. Wiederholen Sie ab Schritt 2, verwenden Sie jedoch 98 als Obergrenze für die Zufallszahl
  7. Wiederholen Sie ab Schritt 2, aber verwenden Sie 97 als Obergrenze der Zufallszahl
  8. Wiederholen Sie ab Schritt 2, verwenden Sie jedoch 96 als Obergrenze für die Zufallszahl
  9. Wiederholen Sie ab Schritt 2, verwenden Sie jedoch 95 als Obergrenze der Zufallszahl
  10. Wiederholen Sie ab Schritt 2, verwenden Sie jedoch 94 als Obergrenze der Zufallszahl
  11. Wiederholen Sie ab Schritt 2, aber verwenden Sie 93 als Obergrenze der Zufallszahl

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>


Aber dann ist Ihre achte Zahl zufällig von 1 bis 92, nicht von 1 bis 100. Wenn Sie 90 Zahlen auswählen müssten, würde Ihre letzte Zahl nur von 1 bis 10 ausgewählt, nicht wahr?
Adam0101

@ adam0101 Nein, weil er Zahlen entfernt, während er sie auswählt. In Schritt 5 enthält sein Array also nur 99 Zahlen. @belugabob Du bist nicht effizienter als Knuth Shuffle. In der Tat ist der Spleiß wahrscheinlich teurer als der Shuffle (der
absolut

@ adam0101: Er entfernt das ausgewählte Element aus dem Array (siehe Schritt 4 oben), um zu vermeiden, dass Elemente zweimal ausgewählt werden. Er verwendet dann eine untere Obergrenze für die nächste Zufallszahl, einfach weil das Array kürzer ist.
Frerich Raabe

@Alsciende, Ja - dachte, dass es eine Möglichkeit geben würde, dies mit einem Shuffle effizienter zu machen, war sich aber nicht ganz sicher. Um zu vermeiden, dass das Element aus dem Array gelöscht wird, kopieren Sie einfach den letzten Eintrag aus dem Array (vorausgesetzt, es war nicht der von Ihnen ausgewählte) an die Position, von der Sie ihn ausgewählt haben.
Belugabob

1
Der Grund dafür, dass values.length nicht dekrementiert wird, besteht darin, dass nicht garantiert werden kann, dass das Verringern der Länge eines Arrays nicht durch Neuzuweisung von Speicher erfolgt. Die Verwendung von maxIndex hat den gleichen Effekt, indem die letzten Einträge im Array einfach ignoriert werden, da sie irrelevant werden.
Belugabob

8

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));


Dies ist meine Lieblingsantwort von allen. Keine Ahnung, warum es nur 6 Stimmen bekam. Elegant und mit guter Komplexität (vorausgesetzt, es sortist gut implementiert, was ich sicher bin).
Gilad Barner

3

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;

3

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.


Was passiert, wenn ich möchte, dass 0 enthalten ist? Die Zeile min = (min) ? min : 1,gibt immer 1 zurück (daher wird 0 niemals ausgewählt)
TBE

Ein sehr guter Punkt. :). Vielen Dank, ich habe die entsprechende Änderung vorgenommen. Es wird jetzt zurückkehren, auch wenn Sie eine 0.
kaizer1v

2

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.


2
var arr = []
while(arr.length < 8){
  var randomnumber=Math.ceil(Math.random()*100)
  if(arr.indexOf(randomnumber) === -1){arr.push(randomnumber)}  
}
document.write(arr);

kürzer als andere Antworten, die ich gesehen habe


1

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);

Schöne rekursive Implementierung - Ich habe in meiner Antwort eine Alternative veröffentlicht, die keinen Spleiß verwendet, da ich der Meinung bin, dass dies ein vermeidbarer Leistungseinbruch ist (nicht, dass das OP Probleme mit der Leistung hatte)
belugabob

Ihre Lösung ist klug, aber ich werde es nicht in meinem Array # verwende Methode wählen , weil ich nicht will , dies seine Elemente haben schlurfte um , wenn ich es zurück.
Alsciende

Welches Array möchten Sie nicht mischen, das ursprüngliche 1-100-Array oder die Ergebnisse? Ersteres sollte keine Rolle spielen, da es sich um ein funktionierendes Array handelt, und letzteres wird aufgrund der Art des Codes ohnehin in zufälliger Reihenfolge veröffentlicht. Ich bin mir nicht ganz sicher, ob ich deine Gründe verstehe.
Belugabob

Das Original. Ich habe eine generische Array # pick-Methode implementiert, die ich nützlich finde. Diese Funktion weiß nicht, ob dies ein funktionierendes Array ist oder nicht. Um generisch, es nicht ändern , diese mehr als nötig.
Alsciende

Aber es ändert es immer noch, wenn auch nur ein wenig, was bei Verwendung dieser Technik nicht zu vermeiden ist.
Belugabob

1

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

1

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));

1

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);


0

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;
  }
}

0
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

0

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]


0

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.


0

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.


0
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.


0

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);

Geben Sie hier die Bildbeschreibung ein

jsFiddle


0

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))

0

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 sampleFunktion arbeitet träge und gibt Ihnen 1 zufälliges Element pro Iteration bis zu den Ngewü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 sampledas Eingabearray nicht mutiert, aber Sie könnten leicht argumentieren, dass eine mutierende Implementierung günstig ist.

Beispielsweise shufflemö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]

sampleist 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.

  • "Wie viele soll ich probieren?" - Sie müssen nicht angeben
  • "Muss ich zuerst alle Primzahlen finden und dann eine zufällige Primzahl auswählen?" - Nein.

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 xSie dann zurück, wenn dies der Fall ist. Wenn die Liste der Zahlen erschöpft ist, bevor eine Primzahl gefunden wird, NaNwird 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


0
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
}

0

Die Verwendung von a Setist 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))


0

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.

  • Holen Sie sich am Ende des Arrays (100) eine Zufallszahl (rnd ) von 1 bis 100
  • Tausche 100 und die Zufallszahl rnd
  • Wiederholen Sie Schritt 1 mit Array (99).

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)));


0

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)

1
Fügen Sie eine Erklärung des Codes hinzu
Arghya Sadhu

-1

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())]


Für die Reinheit, nichts zuzuweisen.
Marcin Król
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.