Generuj unikalne liczby losowe od 1 do 100


99

Jak mogę wygenerować unikalne liczby losowe od 1 do 100 za pomocą JavaScript?


19
Nie jest to oszustwo, ponieważ koncentruje się na javascript.
dotty

2
@dotty cóż, nie ma zasadniczej różnicy między robieniem tego w Javascript a robieniem tego w jakimkolwiek innym języku, ale nie będę głosował za zamknięciem.
Pointy

1
Nie będę też głosował za zamknięciem. To jest wystarczająco konkretne.
Josh Stodola


1
Jest inny, czystszy sposób na zrobienie tego stackoverflow.com/questions/51898200/…
Huangism

Odpowiedzi:


174

Na przykład: Aby wygenerować 8 unikalnych liczb losowych i zapisać je w tablicy, możesz po prostu zrobić to:

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
Rzeczywisty kod jest o wiele lepszy na takie pytania niż pseudokod;) (skasowałem moją odpowiedź, która była pseudokodem ...)
Roman Starkov

3
O można wybrać; użyj var randomnumber = Math.ceil (Math.random () * 100)
Alsciende

9
-1: ten algorytm jest podejściem naiwnym; to jest bardzo nieefektywne.
Frerich Raabe

40
Łał. Naiwny wydaje się trochę silny. Może nie jest to najlepsze rozwiązanie, ale jest proste, krótkie, łatwe do zobaczenia, co się dzieje i działa w akceptowalnych parametrach operacyjnych dla tego, co należy osiągnąć. Do następnego zadania. Doskonałość jest świetna, ale „gotowe” jest lepsze niż „doskonałe”.
adam0101

4
Istnieje szansa, że ​​funkcja zwróci 0 w tablicy. Zgodnie z tym linkiem: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… , Math.random () Returns a random number between 0 (inclusive) and 1 (exclusive). Jeśli the Math.random()przypadkowo zwróci 0, Math.ceil(0)to również wynosi 0, chociaż szansa jest mała.
Qian Chen

43
  1. Wypełnij tablicę liczbami od 1 do 100.
  2. Potasuj to .
  3. Weź pierwsze 8 elementów wynikowej tablicy.

8
z pewnością bardziej wydajne jest modyfikowanie kodu, aby wykonać tylko pierwsze 8 tasowań? (a następnie weź ostatnie 8 elementów tablicy semi-shuffled)
drugi

1
Tak też zawsze to robię. Więc jeśli chcę dziesięć losowych wierszy z pliku zawierającego kilka wierszy, robię to randlines file | head -10.
tchrist

1
Myślę, że jest to właściwa odpowiedź, ponieważ zachowuje rozkład prawdopodobieństwa, którego nie ma przyjęta odpowiedź
roberto tomás

2
A jeśli N = 10 ^ 12? Niezbyt wydajne.
shinzou

2
@shinzou w prawdziwym świecie nie posortowałbyś 10 ^ 12 liczb za pomocą JavaScript. Tirivalowe pytanie wymaga trywialnej odpowiedzi. Nie jestem tutaj, aby rozwiązać problem głodu na świecie. Jestem do tego dobrze przygotowany, ale nie o to chodzi.
ЯegDwight

14

Generować permutację 100 liczb, a następnie wybierz kolejno.

Użyj algorytmu tasowania Knutha (inaczej tasowania Fishera-Yatesa) .

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;

   }
}

KOD SKOPIOWANY Z LINKU.

EDYTOWAĆ :

Ulepszony kod:

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

Potencjalny problem:

Załóżmy, że mamy tablicę 100 liczb {np. [1, 2, 3 ... 100]} i przestajemy zmieniać po 8 zamianach; wtedy przez większość czasów tablica będzie wyglądać następująco: {1, 2, 3, 76, 6, 7, 8, ... liczby tutaj zostaną przetasowane ... 10}.

Ponieważ każda liczba zostanie zamieniona z prawdopodobieństwem 1/100, więc prawdopodobieństwo. zamiany pierwszych 8 liczb to 8/100, podczas gdy prawd. zamiany innych 92 to 92/100.

Ale jeśli uruchomimy algorytm dla pełnej tablicy, jesteśmy pewni (prawie) każdy wpis zostanie zamieniony.

W przeciwnym razie stajemy przed pytaniem: które 8 liczb wybrać?


5
To podejście jest poprawne, ale nieoptymalne: możesz przestać tasować po ośmiu zamianach, ponieważ potrzebujesz tylko ośmiu liczb losowych. Powyższy kod zamienia całą tablicę (w tym scenariuszu 100 elementów).
Frerich Raabe

Kod mógłby zostać poważnie ulepszony. Zwracane wartości, efekty uboczne i użycie funkcji są naprawdę niewyraźne w IMO. Może jeśli napiszesz funkcję, która dokładnie odpowiada na pierwotny problem, używając funkcji fisherYates, będzie to jaśniejsze.
Alsciende

1
Odpowiedź zaktualizowana o ulepszony kod. Również @Frerich Raabe: wspomniano o problemie z zatrzymaniem po ośmiu zamianach.
Pratik Deoghare

Twój algorytm Fishera-Yatesa jest błędny. r powinien zależeć od i. Zobacz moją odpowiedź: stackoverflow.com/questions/2380019/…
Alsciende

Ups, przepraszam, mój okropny błąd! Twoja realizacja jest super. Lubiłem to. +1. Daj mi znać, jeśli coś jest z nią nie tak. Dzięki.
Pratik Deoghare

12

Nowoczesne rozwiązanie JS wykorzystujące Set (i średni przypadek O (n))

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

console.log([...nums]);


Dlaczego jest to O (n)? Czy nie może zapętlić się przez dowolny czas?
Anthony Wieser,

@AnthonyWieser Masz rację, w najgorszym przypadku. Sugerowałem przeciętny przypadek, ponieważ Set.add to o (1)
Alister

Myślę, że to może zwrócić 0, tak jak moja odpowiedź, zanim została zmieniona na użycieMath.floor(Math.random()*100) + 1
adam0101

Bardzo fajnie do odkrycia Setw JS! Jednak czy to rozwiązanie nie powodowałoby niepotrzebnego generowania liczb, dopóki nie spełni się wymogu unikalności, szczególnie w ostatnich iteracjach, gdyby 8 było bliższe 100? Dlatego myślę, że wolę również elegancką odpowiedź sortponiżej.
Gilad Barner

10

Powyższe techniki są dobre, jeśli chcesz uniknąć biblioteki, ale w zależności od tego, czy nie masz nic przeciwko bibliotece, sugerowałbym sprawdzenie Szansa na generowanie losowych rzeczy w JavaScript.

W szczególności, aby rozwiązać swoje pytanie, korzystanie z Chance jest tak proste, jak:

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

Zastrzeżenie, jako autor Chance jestem nieco stronniczy;)


Głosuj za, ponieważ nigdy wcześniej nie widziałem fragmentu kodu uruchamiania
surfmuggle

jeśli chcę utworzyć kod (8 losowych znaków alfanumerycznych) dla kuponów, który musi być unikalny, jak mogę to zrobić z Chance.js? uwaga: kupony będą realizowane na żądanie, więc liczba kodów będzie nieokreślona
Oscar Yuandinata

@OscarYuandinata to proste, po prostu zrób var codes = chance.unique(chance.string, 8)Jeśli potrzebujesz kodów pobranych z określonej puli znaków, możesz to określić w ten sposób: chance.unique(chance.string, 8, {pool: "abcd1234"})gdzie abcd1234 może być dowolnymi znakami, które chcesz w puli. Zobacz chancejs.com/#string
Victor Quinn

@VictorQuinn, przepraszam, że nie wyraziłem się jasno. Mam na myśli to, że kod kuponu będzie składał się z 8 znaków losowego ciągu alfanumerycznego, a nie tablicy z 8 losowych ciągów alfanumerycznych. hahaha ..
Oscar Yuandinata

Oh @OscarYuandinata to o wiele łatwiejsze heh chance.string({ length: 8 })i jeśli chcesz, aby w tym ciągu pojawiały się tylko określone znaki, chance.string({ pool: 'abcd1234', length: 8 })co zwróci losowy ciąg 8 znaków ze znaków abcd1234, na przykład „2c2c44bc” lub „331141cc”
Victor Quinn

8

Aby uniknąć długich i zawodnych przetasowań, zrobiłbym następujące rzeczy ...

  1. Wygeneruj tablicę zawierającą kolejno liczby od 1 do 100.
  2. Wygeneruj losową liczbę od 1 do 100
  3. Wyszukaj liczbę w tym indeksie w tablicy i zapisz w wynikach
  4. Usuń element z macierzy, skracając go o jeden
  5. Powtórz od kroku 2, ale użyj 99 jako górnej granicy liczby losowej
  6. Powtórz czynności od kroku 2, ale użyj 98 jako górnej granicy liczby losowej
  7. Powtórz czynności od kroku 2, ale użyj 97 jako górnej granicy liczby losowej
  8. Powtórz czynności od kroku 2, ale użyj 96 jako górnej granicy liczby losowej
  9. Powtórz czynności od kroku 2, ale użyj 95 jako górnej granicy liczby losowej
  10. Powtórz od kroku 2, ale użyj 94 jako górnej granicy liczby losowej
  11. Powtórz czynności od kroku 2, ale użyj 93 jako górnej granicy liczby losowej

Voila - bez powtarzających się liczb.

Jeśli ktoś jest zainteresowany, mogę wysłać później jakiś rzeczywisty kod.

Edycja: Prawdopodobnie to moja passa konkurencyjna, ale widząc post @Alsciende, nie mogłem się powstrzymać przed wysłaniem obiecanego kodu.

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


Ale wtedy twoja ósma liczba jest losowa od 1 do 92, a nie od 1 do 100. Gdybyś musiał wybrać 90 liczb, ostatnia liczba byłaby wybrana tylko od 1 do 10, prawda?
adam0101

@ adam0101 Nie, ponieważ on usuwa liczby, gdy je wybiera. Tak więc w kroku 5 w jego tablicy jest tylko 99 liczb. @belugabob Nie jesteś bardziej wydajny niż Knuth Shuffle. W rzeczywistości splot jest prawdopodobnie droższy niż shuffle (który jest całkowicie niezawodny)
Alsciende

@ adam0101: Usuwa wybrany element z tablicy (zobacz krok 4 powyżej), unikając w ten sposób podwójnego wybierania elementów. Następnie używa dolnej górnej granicy dla następnej liczby losowej, po prostu dlatego, że tablica jest krótsza.
Frerich Raabe

@Alsciende, Tak - pomyślałem, że można to zrobić wydajniej przy użyciu tasowania, ale nie był do końca pewien. Aby uniknąć usunięcia elementu z tablicy, po prostu skopiuj ostatni wpis z tablicy (pod warunkiem, że nie był to ten, który wybrałeś) do pozycji, z której wybrałeś.
belugabob

1
Przyczyną niezmniejszania wartości values.length jest to, że nie ma gwarancji, że zmniejszenie długości tablicy nie nastąpi poprzez ponowne przydzielenie pamięci. Używanie maxIndex daje ten sam efekt, po prostu ignorując ostatnie wpisy w tablicy, ponieważ stają się one nieistotne.
belugabob

8

Innym podejściem jest wygenerowanie tablicy zawierającej 100 elementów z rosnącymi liczbami i losowe sortowanie. Prowadzi to właściwie do naprawdę krótkiego i (moim zdaniem) prostego fragmentu.

const numbers = Array(100).fill().map((_, index) => index + 1);
numbers.sort(() => Math.random() - 0.5);
console.log(numbers.slice(0, 8));


To moja ulubiona odpowiedź ze wszystkich. Nie wiem, dlaczego otrzymał tylko 6 głosów. Elegancki i o dobrej złożoności (pod warunkiem, że sortjest dobrze zaimplementowany, co na pewno jest).
Gilad Barner

3

Zrobiłbym to:

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

Jest to bardzo ogólna funkcja, którą napisałem, aby generować losowe unikalne / nieunikalne liczby całkowite dla tablicy. Załóżmy, że ostatni parametr jest prawdziwy w tym scenariuszu dla tej odpowiedzi.

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

Tutaj `` tempObj '' jest bardzo użytecznym obiektem, ponieważ każda wygenerowana liczba losowa będzie bezpośrednio sprawdzać w tym tempObj, jeśli ten klucz już istnieje, jeśli nie, to zmniejszamy i o jeden, ponieważ potrzebujemy 1 dodatkowego uruchomienia, ponieważ bieżąca liczba losowa już istnieje .

W twoim przypadku wykonaj następujące czynności

_arrayRandom(8, 1, 100, true);

To wszystko.


co się stanie, jeśli chcę, aby uwzględniono 0? linia min = (min) ? min : 1,zawsze zwraca 1. (więc 0 nigdy nie zostanie wybrane)
TBE

Bardzo dobra uwaga. :). Dziękuję, dokonałem odpowiedniej zmiany. Teraz powróci, nawet jeśli zdasz 0.
kaizer1v

2

Tasowanie liczb od 1 do 100 to właściwa podstawowa strategia, ale jeśli potrzebujesz tylko 8 tasowanych liczb, nie ma potrzeby tasowania wszystkich 100 liczb.

Nie znam za dobrze Javascript, ale uważam, że łatwo jest szybko utworzyć tablicę 100 wartości null. Następnie przez 8 rund zamieniasz n-ty element tablicy (n zaczynając od 0) na losowo wybrany element z przedziału od n + 1 do 99. Oczywiście wszelkie elementy, które nie zostały jeszcze wypełnione, oznaczają, że element byłby naprawdę oryginalny indeks plus 1, więc jest to trywialne do uwzględnienia. Kiedy skończysz z 8 rundami, pierwszych 8 elementów tablicy będzie miało 8 tasowanych liczb.


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

krócej niż inne odpowiedzi, które widziałem


1

Ten sam algorytm permutacji co w The Machine Charmer, ale z prototypową implementacją. Lepiej nadaje się do dużej liczby kilofów. Używa przydziału destrukturyzacji js 1.7, jeśli jest dostępny.

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

Edycja: inna propozycja, lepiej dopasowana do małej liczby typów, oparta na odpowiedzi Belugaboba. Aby zagwarantować unikalność, usuwamy wybrane liczby z tablicy.

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

Nicea rekurencyjna realizacja - Mam pisał alternatywę w moją odpowiedź, że nie wykorzystuje splot, jak czuję, że jest to możliwe do uniknięcia trafienia wydajność (nie, że PO nie miałem żadnych problemów związanych z wydajnością)
belugabob

Twoje rozwiązanie jest mądry, ale nie będę go używać w moich Array # wybrać metodę, ponieważ nie chcę to mieć jej elementy przemieszane kiedy wrócę go.
Alsciende

Która tablica nie ma być tasowana, oryginalna tablica 1-100 czy wyniki? To pierwsze nie powinno mieć znaczenia, ponieważ jest to tablica robocza, a drugie, z natury kodu, i tak wyjdzie w losowej kolejności. Nie jestem pewien, czy rozumiem twoje powody.
belugabob

Oryginalny. Zaimplementowałem ogólną metodę Array # pick, która jest przydatna. Ta funkcja nie wiem, czy to jest tablica działa, czy nie. Aby być ogólnym, nie zmienia tego bardziej niż to konieczne.
Alsciende

Ale wciąż zmienia to, nawet jeśli tylko trochę, co jest nieuniknione przy stosowaniu tej techniki.
belugabob

1

dla tablic z takimi dziurami, [,2,,4,,6,7,,] ponieważ moim problemem było wypełnienie tych dziur. Więc zmodyfikowałem go zgodnie z moimi potrzebami :)

poniższe zmodyfikowane rozwiązanie zadziałało u mnie :)

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

Najlepszą wcześniejszą odpowiedzią jest odpowiedź wg sje397. Otrzymasz jak najlepsze liczby losowe, tak szybko, jak to możliwe.

Moje rozwiązanie jest bardzo podobne do jego rozwiązania. Czasami jednak chcesz losowe liczby w losowej kolejności i dlatego zdecydowałem się wysłać odpowiedź. Ponadto zapewniam ogólną funkcję.

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

Oto moja wersja ES6, którą zebrałem razem. Jestem pewien, że może być trochę bardziej skonsolidowany.

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

A co powiesz na użycie właściwości obiektu jako tablicy skrótów ? W ten sposób najlepszym scenariuszem jest losowanie tylko 8 razy. Byłoby to skuteczne tylko wtedy, gdy chcesz mieć niewielką część zakresu liczb. Zajmuje również znacznie mniej pamięci niż Fisher-Yates, ponieważ nie musisz przydzielać miejsca na tablicę.

var ht={}, i=rands=8;
while ( i>0 || keys(ht).length<rands) ht[Math.ceil(Math.random()*100)]=i--;
alert(keys(ht));

Potem dowiedziałem się, że Object.keys (obj) jest funkcją ECMAScript 5, więc powyższe jest obecnie praktycznie bezużyteczne w sieciach internetowych. Nie bój się, ponieważ dostosowałem go do ECMAScript 3, dodając taką funkcję klawiszy.

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

jeśli potrzebujesz więcej unikatowości, musisz wygenerować tablicę (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;
}

powyższy kod jest szybszy:
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

Dodanie kolejnej lepszej wersji tego samego kodu (zaakceptowana odpowiedź) z funkcją indexOf w JavaScript 1.6. Nie ma potrzeby przechodzenia przez całą tablicę za każdym razem, gdy sprawdzasz duplikat.

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

Starsza wersja Javascript może nadal korzystać z wersji u góry

PS: Próbowałem zasugerować aktualizację wiki, ale została odrzucona. Nadal uważam, że może to być przydatne dla innych.


0

To jest moje osobiste rozwiązanie:

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

Losowo generuje 8 unikalnych wartości tablicowych (od 0 do 7), a następnie wyświetla je za pomocą pola ostrzegawczego.


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

Myślę, że ta metoda różni się od metod podanych w większości odpowiedzi, więc pomyślałem, że mógłbym tu dodać odpowiedź (chociaż pytanie zadano 4 lata temu).

Generujemy 100 losowych liczb i oznaczamy każdą z nich liczbami od 1 do 100. Następnie sortujemy te otagowane liczby losowe, a tagi są losowo tasowane. Alternatywnie, w razie potrzeby w tym pytaniu, można by pozbyć się po prostu znalezienia 8 pierwszych oznaczonych liczb losowych. Znalezienie 8 najlepszych elementów jest tańsze niż sortowanie całej tablicy.

Należy tutaj zauważyć, że algorytm sortowania wpływa na ten algorytm. Jeśli zastosowany algorytm sortowania jest stabilny, istnieje niewielkie odchylenie na korzyść mniejszych liczb. Idealnie byłoby, gdyby algorytm sortowania był niestabilny i nawet nie był nastawiony na stabilność (lub niestabilność), aby uzyskać odpowiedź z idealnie jednorodnym rozkładem prawdopodobieństwa.


0

Może to obsłużyć generowanie do 20 cyfr UNIKALNEJ liczby losowej

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

wprowadź opis obrazu tutaj

jsFiddle


0

To rozwiązanie używa skrótu, który jest znacznie wydajniejszy O (1) niż sprawdzenie, czy rezyduje w tablicy. Ma również dodatkowe bezpieczne kontrole. Mam nadzieję, że to pomoże.

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

Implementacja tego jako generatora sprawia, że ​​praca z nim jest całkiem przyjemna. Uwaga, ta implementacja różni się od tych, które wymagają najpierw przetasowania całej tablicy wejściowej.

Ta samplefunkcja działa leniwie, dając 1 losowy przedmiot na iterację, aż do Nprzedmiotów, o które prosisz. Jest to miłe, ponieważ jeśli chcesz tylko 3 pozycje z listy 1000 , nie musisz najpierw dotykać wszystkich 1000 pozycji.

// 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]

Zdecydowałem się zaimplementować samplew sposób, który nie powoduje mutacji tablicy wejściowej, ale można łatwo argumentować, że implementacja mutująca jest korzystna.

Na przykład shufflefunkcja może chcieć zmodyfikować oryginalną tablicę wejściową. Lub możesz chcieć próbkować z tego samego wejścia w różnych momentach, aktualizując wejście za każdym razem.

// 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]

samplenie jest już czystą funkcją z powodu mutacji wejścia tablicy, ale w pewnych okolicznościach (pokazanych powyżej) może mieć więcej sensu.


Innym powodem, dla którego wybrałem generator zamiast funkcji, która po prostu zwraca tablicę, jest to, że możesz chcieć kontynuować próbkowanie do określonego warunku.

Być może chcę pierwszą liczbę pierwszą z listy 1 000 000 liczb losowych.

  • „Ile mam próbkować?” - nie musisz określać
  • „Czy muszę najpierw znaleźć wszystkie liczby pierwsze, a następnie wybrać losową liczbę pierwszą?” - Nie.

Ponieważ pracujemy z generatorem, to zadanie jest banalne

const randomPrimeNumber = listOfNumbers => {
  for (let x of sample(Infinity) (listOfNumbers)) {
    if (isPrime(x))
      return x;
  }
  return NaN;
}

Spowoduje to ciągłe próbkowanie 1 losowej liczby naraz x, sprawdź, czy jest to liczba pierwsza, a następnie zwróci, xjeśli tak jest. Jeśli lista liczb zostanie wyczerpana przed znalezieniem liczby pierwszej, NaNzwracana jest wartość.


Uwaga:

Ta odpowiedź została pierwotnie udostępniona na inne pytanie, które zostało zamknięte jako duplikat tego. Ponieważ bardzo różni się od innych przedstawionych tutaj rozwiązań, postanowiłem się nim również podzielić


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

Korzystanie z a Setto najszybsza opcja. Oto ogólna funkcja do uzyskiwania unikalnej liczby losowej, która używa generatora wywołań zwrotnych. Teraz jest szybki i wielokrotnego użytku .

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

Jest to implementacja Shuffle Fisher Yates / Durstenfeld , ale bez faktycznego tworzenia tablicy, co zmniejsza złożoność przestrzeni lub ilość potrzebnej pamięci, gdy rozmiar pobrania jest mały w porównaniu z liczbą dostępnych elementów.

Aby wybrać 8 liczb ze 100, nie jest konieczne tworzenie tablicy 100 elementów.

Zakładając, że utworzono tablicę,

  • Od końca tablicy (100) pobierz losową liczbę ( rnd) od 1 do 100
  • Zamień 100 i losową liczbę rnd
  • Powtórz krok 1 z tablicą (99)

Jeśli tablica nie zostanie utworzona, można użyć mapy hashMap do zapamiętania rzeczywistych zamienionych pozycji. Kiedy druga wygenerowana liczba losowa jest równa jednej z poprzednio wygenerowanych liczb, mapa podaje bieżącą wartość w tej pozycji, a nie rzeczywistą wartość.

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

Oto przykład losowych 5 liczb z zakresu od 0 do 100 (w tym 0 i 100) bez powielania.

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

Możesz to również zrobić za pomocą jednej wkładki w ten sposób:

[...((add, set) => add(set, add))((set, add) => set.size < 8 ? add(set.add(Math.floor(Math.random()*100) + 1), add) : set, new Set())]


Za czystość nie przypisywania niczego.
Marcin Król
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.