1 ile 100 arasında benzersiz rastgele sayılar oluşturun


105

JavaScript kullanarak 1 ile 100 arasında bazı benzersiz rastgele sayıları nasıl oluşturabilirim ?


20
Bu javascript'e odaklandığı için gerçekten bir dupe değil.
dotty

2
@dotty bunu Javascript'te yapmakla başka bir dilde yapmak arasında önemli bir fark yok, ancak kapatmaya oy vermeyeceğim.
Sivri

1
Ben de kapatmak için oy kullanmayacağım. Bu yeterince spesifik.
Josh Stodola


Yanıtlar:


186

Örneğin: 8 benzersiz rastgele sayı oluşturmak ve bunları bir dizide saklamak için, bunu yapmanız yeterlidir:

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
Gerçek kod, bu tür sorular için sözde koddan çok daha iyidir;) (sözde kod olan cevabımı sildi ...)
Roman Starkov 04

3
O seçilebilir; var randomnumber = Math.ceil (Math.random () * 100)
Alsciende

10
-1: bu algoritma saf bir yaklaşımdır; çok verimsiz.
Frerich Raabe

40
Vay. Naive biraz güçlü görünüyor. En iyi çözüm olmayabilir, ancak basit, kısa, neler olduğunu görmek kolaydır ve başarılması gerekenler için kabul edilebilir işletim parametreleri dahilinde çalışır. Sonraki göreve geçelim. Mükemmellik harikadır, ancak "bitmiş" mükemmelden daha iyidir.
adam0101

4
Dizide işlevin 0 döndürme ihtimali vardır. Bu bağlantıya göre: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… , Math.random () Returns a random number between 0 (inclusive) and 1 (exclusive). Eğer the Math.random()yanlışlıkla 0 döndürür, Math.ceil(0)şans düşük olsa da 0'dır.
Qian Chen

43
  1. Bir diziyi 1'den 100'e kadar sayılarla doldurun.
  2. Karıştırın .
  3. Elde edilen dizinin ilk 8 elemanını alın.

8
Kodu yalnızca ilk 8 karıştırmayı yapacak şekilde değiştirmek kesinlikle daha verimli mi? (ve sonra yarı karıştırılmış dizinin son 8 elemanını alın)
ikinci

1
Ben de hep böyle yaparım. Yani, içinde birkaç satır bulunan bir dosyadan on rastgele satır istersem, yaparım randlines file | head -10.
tchrist

1
Bence doğru cevap, çünkü kabul edilen cevabın yapmadığı olasılık
dağılımını koruyor

2
Ya N = 10 ^ 12 ise? Çok verimli değil.
shinzou

2
@shinzou gerçek dünyada JavaScript kullanarak 10 ^ 12 sayıyı sıralayamazsınız. Bir tirival soru, önemsiz bir cevap gerektirir. Dünyadaki açlığı çözmek için burada değilim. Bunu yapmak için çok iyi donanımlıyım, ama asıl soru bu değil.
ЯegDwight

14

100 sayının permütasyonunu oluşturun ve ardından seri olarak seçin.

Kullanım Knuth Karıştır (aka Fisher-Yates karıştır) Algoritması .

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;

   }
}

LİNKTEN KOPYALANAN KOD.

DÜZENLE :

Geliştirilmiş 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);
}

Potansiyel problem:

Diyelim ki 100 sayılık bir dizimiz var {ör. [1,2,3 ... 100]} ve 8 takasdan sonra değiş tokuşu durduruyoruz; daha sonra çoğu kez dizisi {1,2,3,76,5,6,7,8, ... gibi görünecek, buradaki sayılar karıştırılacak ... 10}.

Çünkü her sayı 1/100 olasılıkla yer değiştirecek yani prob. ilk 8 sayıyı değiştirme oranı 8/100 iken prob. diğer 92 takas oranı 92/100.

Ancak tam dizi için algoritma çalıştırırsak, o zaman (neredeyse) her girişin değiştirildiğinden eminiz.

Aksi takdirde bir soruyla karşılaşırız: hangi 8 rakamı seçmeliyiz?


5
Bu yaklaşım doğrudur, ancak yetersizdir: yalnızca sekiz rastgele sayıya ihtiyacınız olduğundan, sekiz değiş tokuştan sonra karıştırmayı durdurabilirsiniz. Yukarıdaki kod tüm diziyi değiştirir (bu senaryoda, 100 öğe).
Frerich Raabe

Kod ciddi şekilde geliştirilebilir. Dönüş değerleri, yan etkiler ve işlev kullanımı gerçekten bulanık IMO'dur. FisherYates işlevinizi kullanarak orijinal soruna tam olarak yanıt veren bir işlev yazarsanız, belki daha net olur.
Alsciende

1
Yanıt, iyileştirilmiş kodla güncellendi. Ayrıca @Frerich Raabe: sekiz takasın ardından durma sorunundan bahsediliyor.
Pratik Deoghare

Fisher-Yates algoritmanız yanlış. r, i'ye bağlı olmalıdır. Yanıtlayıcıma bakın: stackoverflow.com/questions/2380019/…
Alsciende

Üzgünüm, korkunç hatam !! Uygulamanız harika. Beğendim. +1. Herhangi bir sorun varsa lütfen bana bildirin.
Pratik Deoghare

12

Set kullanarak modern JS Çözümü (ve ortalama durum O (n))

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

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


Neden O (n)? Keyfi bir süre boyunca döngü yapamaz mı?
Anthony Wieser

@AnthonyWieser Haklısın, en kötü durum. Set.add o (1) olduğundan ortalama bir durumu ima ediyordum
Alister

Sanırım bu, kullanım için değiştirilmeden önceki cevabım gibi 0 döndürebilirMath.floor(Math.random()*100) + 1
adam0101

SetJS'de keşfetmek çok güzel ! Bununla birlikte, bu çözüm, özellikle son yinelemelerde, 8, 100'e yakın olsaydı, benzersizlik gerekliliğine uyana kadar gereksiz sayı üretimine neden olmaz mıydı? Bu nedenle sortaşağıdaki şık yanıtı tercih ettiğimi düşünüyorum .
Gilad Barner

11

Yukarıdaki teknikler kütüphane kaçınmak istiyorsanız iyi, ama bir kütüphane ile düzeleceğine, ben kontrol öneririz bağlı Chance JavaScript rastgele şeyler üretmek için.

Özellikle sorunuzu çözmek için Chance'i kullanmak şu kadar kolaydır:

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

Feragatname, Chance'in yazarı olarak biraz önyargılıyım;)


Daha önce çalıştırma kodu parçacığını hiç görmediğim için
oy verin

Kuponlar için benzersiz olması gereken bir kod (8 rastgele alfasayısal dize) yapmak istersem, bunu Chance.js ile nasıl yapabilirim? not: kuponlar talep üzerine yapılacaktır, bu nedenle kod sayısı belirsiz olacaktır
Oscar Yuandinata

@OscarYuandinata bu kolay, sadece yapın var codes = chance.unique(chance.string, 8)Belirli bir karakter havuzundan alınan kodlara ihtiyacınız varsa, bunu şöyle belirtebilirsiniz: chance.unique(chance.string, 8, {pool: "abcd1234"})burada abcd1234 havuzda istediğiniz herhangi bir karakter olabilir. Bkz chancejs.com/#string
Victor Quinn

@VictorQuinn, özür dilerim kendimi netleştirmedim. Demek istediğim, kupon kodu 8 karakterli rastgele alfanümerik dizgi olacak, rastgele 8 alfanümerik diziden oluşan bir dizi olmayacak. hahaha ..
Oscar Yuandinata

Oh @OscarYuandinata bu çok daha kolay heh chance.string({ length: 8 })ve bu dizede yalnızca belirli karakterlerin görünmesini istiyorsanız, chance.string({ pool: 'abcd1234', length: 8 })bu, abcd1234 karakterlerinden rastgele 8 karakterlik bir dizi döndürür, örneğin "2c2c44bc" veya "331141cc"
Victor Quinn

9

Diğer bir yaklaşım, artan sayılarla 100 maddelik bir dizi oluşturmak ve bunu rastgele sıralamaktır. Bu aslında gerçekten kısa ve (bence) basit bir parçaya götürüyor.

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


Bu, hepsinden en sevdiğim cevap. Dunno neden sadece 6 oy aldı. Zarif ve iyi bir karmaşıklığa sahip (sağlandığından sorteminim ki iyi uygulanmıştır).
Gilad Barner

8

Uzun ve güvenilmez karıştırmalardan kaçınmak için aşağıdakileri yapardım ...

  1. Sırayla 1 ile 100 arasında bir sayı içeren bir dizi oluşturun.
  2. 1 ile 100 arasında rastgele bir sayı oluşturun
  3. Dizideki bu dizindeki sayıyı arayın ve sonuçlarınızda saklayın
  4. Elemanı diziden kaldırarak diziyi kısaltın
  5. 2. adımdan itibaren tekrarlayın, ancak rastgele sayının üst sınırı olarak 99'u kullanın
  6. 2. adımdan itibaren tekrarlayın, ancak rastgele sayının üst sınırı olarak 98 kullanın
  7. 2. adımdan itibaren tekrarlayın, ancak rastgele sayının üst sınırı olarak 97'yi kullanın
  8. 2. adımdan itibaren tekrarlayın, ancak rastgele sayının üst sınırı olarak 96 kullanın
  9. 2. adımdan itibaren tekrarlayın, ancak rastgele sayının üst sınırı olarak 95'i kullanın
  10. 2. adımdan itibaren tekrarlayın, ancak rastgele sayının üst sınırı olarak 94'ü kullanın
  11. 2. adımdan itibaren tekrarlayın, ancak rastgele sayının üst sınırı olarak 93'ü kullanın

Voila - tekrarlanan numara yok.

İlgilenen varsa, daha sonra gerçek bir kod gönderebilirim.

Düzenleme: Muhtemelen içimdeki rekabetçi galibiyet ama @ Alsciende'nin gönderisini gördükten sonra söz verdiğim kodu göndermeye karşı koyamadım.

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


Ama o zaman sekizinci sayınız 1'den 100'e değil 1'den 92'ye rastgele gelir. 90 numara seçmek zorunda olsaydınız, son numaranız sadece 1'den 10'a kadar seçilir, değil mi?
adam0101

@ adam0101 Hayır, çünkü sayıları seçerken kaldırır. Yani 5. adımda dizisinde sadece 99 numara var. @belugabob Knuth Shuffle'dan daha verimli değilsin. Aslında, ekleme muhtemelen karıştırmadan daha pahalıdır (ki bu tamamen güvenilirdir)
Alsciende

@ adam0101: Seçilen öğeyi diziden kaldırıyor (yukarıdaki 4. adıma bakın), böylece herhangi bir öğenin iki kez seçilmesini önlüyor. Daha sonra sıradaki rastgele sayı için daha düşük bir üst sınır kullanır, çünkü dizi daha kısadır.
Frerich Raabe

@Alsciende, Evet - bunu bir shuffle kullanarak daha verimli yapmanın bir yolu olacağını düşündüm, ancak tam olarak emin değildim. Öğeyi diziden silmekten kaçınmak için, dizideki son girişi (sizin seçtiğiniz değilse) seçtiğiniz konuma kopyalamanız yeterlidir.
belugabob

1
Value.length değerlerinin azaltılmamasının nedeni, bir dizinin uzunluğunun azaltılmasının belleği yeniden tahsis ederek yapılmayacağının garantisinin olmamasıdır. MaxIndex kullanmak, alakasız hale geldiklerinden dizideki son girdileri yok sayarak aynı etkiye sahiptir.
belugabob

3

Bunu yapardım:

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

Bu, bir dizi için rastgele benzersiz / benzersiz olmayan tamsayılar oluşturmak için yazdığım çok genel bir işlevdir. Bu yanıt için bu senaryoda son parametrenin doğru olduğunu varsayın.

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

Burada 'tempObj' çok kullanışlı bir objedir, çünkü üretilen her rasgele sayı bu tempObj'yi doğrudan kontrol edecektir, eğer bu anahtar zaten mevcutsa, değilse, o zaman i'yi bir azaltıyoruz çünkü mevcut rasgele sayı zaten mevcut olduğundan fazladan 1 çalışmaya ihtiyacımız var .

Sizin durumunuzda aşağıdakileri çalıştırın

_arrayRandom(8, 1, 100, true);

Bu kadar.


0'ın dahil edilmesini istersem ne olur? satır min = (min) ? min : 1,her zaman 1 değerini döndürür (bu nedenle 0 asla seçilmeyecektir)
TBE

Çok güzel bir nokta. :). Teşekkür ederim, uygun değişikliği yaptım. 0'ı
geçseniz

2

Sayıları 1'den 100'e kadar karıştırmak doğru temel stratejidir, ancak yalnızca 8 karıştırılmış sayıya ihtiyacınız varsa, 100 sayının tümünü karıştırmanıza gerek yoktur.

Javascript'i çok iyi bilmiyorum, ancak hızlı bir şekilde 100 sıfırlık bir dizi oluşturmanın kolay olduğuna inanıyorum. Ardından, 8 tur için, dizinin n'inci öğesini (0'dan başlayan n) n + 1'den 99'a kadar rastgele seçilen bir öğe ile değiştirirsiniz. Elbette, henüz doldurulmamış herhangi bir öğe, öğenin gerçekten olduğu anlamına gelir orijinal indeks artı 1, yani çarpanlara ayırmak önemsizdir. 8 turla işiniz bittiğinde, dizinizin ilk 8 öğesinde 8 karıştırılmış sayınız olacaktır.


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

gördüğüm diğer cevaplardan daha kısa


1

The Machine Charmer ile aynı permütasyon algoritması, ancak prototiplenmiş bir uygulama ile. Çok sayıda seçim için daha uygun. Varsa js 1.7 imha atamasını kullanır .

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

Düzenleme: Belugabob'un cevabına dayanan, az sayıdaki seçim için daha uygun olan başka bir teklif. Benzersizliği garantilemek için, seçilen sayıları diziden kaldırıyoruz.

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

Güzel özyinelemeli uygulama
Cevabımda

Çözümünüz akıllıca, ama ben istemiyorum çünkü benim Dizisi # kullanmak yöntemini seçmez bu onu döndüğünüzde onun unsurları karıştırılmaz olması.
Alsciende

Hangi dizinin karıştırılmasını istemiyorsunuz, orijinal 1-100 dizisi mi yoksa sonuçlar mı? Birincisi, çalışan bir dizi olduğu için önemli olmamalıdır ve ikincisi, kodun doğası gereği, yine de rastgele bir sırayla ortaya çıkacaktır. Nedenlerinizi anladığımdan pek emin değilim.
belugabob

Orijinal olan. Yararlı bulduğum genel bir Array # pick yöntemi uyguladım. Bu işlev bilmez bu çalışma dizidir ya da değil. Jenerik olmak gerekirse, bu değiştirmez bu gerekenden daha fazla.
Alsciende

Ancak, bu tekniği kullanırken çok az da olsa yine de onu değiştirir.
belugabob

1

bunun gibi delikli diziler için [,2,,4,,6,7,,] çünkü benim sorunum bu boşlukları doldurmaktı. Bu yüzden ihtiyacıma göre değiştirdim :)

aşağıdaki değiştirilmiş çözüm benim için çalıştı :)

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

Daha önceki en iyi cevap, tarafından verilen cevaptır sje397. Mümkün olduğunca çabuk, alabildiğiniz kadar iyi rastgele sayılar alacaksınız.

Benim çözümüm onun çözümüne çok benziyor. Bununla birlikte, bazen rastgele sayıları rastgele sırada istersiniz ve bu yüzden bir cevap göndermeye karar verdim. Ek olarak, genel bir işlev sağlıyorum.

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

İşte birlikte döşediğim ES6 versiyonum. Eminim biraz daha konsolide olabilir.

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

Nesne özelliklerini bir hash tablosu olarak kullanmaya ne dersiniz ? Bu şekilde, en iyi senaryonuz yalnızca 8 kez rastgele seçim yapmaktır. Yalnızca sayı aralığının küçük bir bölümünü istiyorsanız etkili olur. Ayrıca Fisher-Yates'ten çok daha az bellek yoğun çünkü bir dizi için yer ayırmanız gerekmiyor.

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

Daha sonra Object.keys (obj) ' in bir ECMAScript 5 özelliği olduğunu öğrendim , bu yüzden yukarıdakiler şu anda internette hemen hemen işe yaramaz. Korkmayın, çünkü ECMAScript 3'ü böyle bir tuş işlevi ekleyerek uyumlu hale getirdim.

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

Daha fazla benzersizliğe ihtiyacınız varsa bir dizi (1..100) oluşturmalısınız.

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

yukarıdaki kod daha hızlıdır:
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

JavaScript 1.6 indexOf işlevi ile aynı kodun daha iyi bir sürümünü (kabul edilen yanıt) eklemek. Yinelenen kopyayı her kontrol ettiğinizde tüm dizide döngü oluşturmanıza gerek yoktur.

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'in eski sürümü yine de üstteki sürümü kullanabilir

Not: Wiki'ye bir güncelleme önermeye çalıştım ama reddedildi. Hala başkaları için faydalı olabileceğini düşünüyorum.


0

Bu benim kişisel çözümüm:

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

Rastgele olarak 8 benzersiz dizi değeri oluşturur (0 ile 7 arasında), ardından bunları bir uyarı kutusu kullanarak görüntüler.


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

Bu yöntemin yanıtların çoğunda verilen yöntemlerden farklı olduğunu düşünüyorum, bu yüzden buraya bir cevap ekleyebileceğimi düşündüm (soru 4 yıl önce sorulmuş olmasına rağmen).

100 rastgele sayı üretiriz ve her birini 1'den 100'e kadar sayılarla etiketleriz. Daha sonra bu etiketli rastgele sayıları sıralarız ve etiketler rastgele karıştırılır. Alternatif olarak, bu soruda gerektiği gibi, etiketli rastgele sayıların ilk 8'ini bulmak da ortadan kaldırılabilir. İlk 8 öğeyi bulmak, tüm diziyi sıralamaktan daha ucuzdur.

Burada, sıralama algoritmasının bu algoritmayı etkilediği unutulmamalıdır. Kullanılan sıralama algoritması kararlıysa, daha küçük sayılar lehine küçük bir önyargı vardır. İdeal olarak, mükemmel bir şekilde tekdüze olasılık dağılımına sahip bir yanıt üretmek için sıralama algoritmasının istikrarsız olmasını ve hatta kararlılığa (veya istikrarsızlığa) yönelik önyargılı olmamasını isteriz.


0

Bu, 20 haneye kadar BENZERSİZ rasgele sayı üretmeyi başarabilir

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

görüntü açıklamasını buraya girin

jsFiddle


0

Bu çözüm, dizide yer alıp almadığını kontrol etmekten çok daha yüksek performanslı O (1) olan karmayı kullanır. Ekstra güvenli çekleri de vardır. Umarım yardımcı olur.

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

Bunu bir jeneratör olarak uygulamak, çalışmayı oldukça güzel kılar. Unutmayın, bu uygulama, önce tüm girdi dizisinin karıştırılmasını gerektirenlerden farklıdır.

Bu sampleişlev tembel çalışır ve istediğiniz öğeye kadar yineleme başına 1 rastgele öğe Nverir. Bu güzel, çünkü 1000'lik bir listeden yalnızca 3 öğe istiyorsanız , önce 1000 öğenin tamamına dokunmanız gerekmez.

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

sampleGirdi dizisini değiştirmeyecek bir şekilde uygulamayı seçtim , ancak bir mutasyon uygulamasının elverişli olduğunu kolayca iddia edebilirsiniz.

Örneğin, shuffleişlev orijinal girdi dizisini değiştirmeyi isteyebilir. Veya aynı girişten çeşitli zamanlarda örnekleme yapmak ve girişi her seferinde güncellemek isteyebilirsiniz.

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

sampledizi girdisi mutasyonu nedeniyle artık saf bir işlev değildir, ancak bazı durumlarda (yukarıda gösterilmiştir) daha mantıklı olabilir.


Sadece bir dizi döndüren bir işlev yerine bir üreteç seçmemin bir başka nedeni, belirli bir koşula kadar örneklemeye devam etmek isteyebilmenizdir.

Belki de 1.000.000 rastgele sayı listesinden ilk asal sayıyı istiyorum.

  • "Kaç tane örnek almalıyım?" - belirtmek zorunda değilsin
  • "Önce tüm asal sayıları bulup sonra rastgele bir asal seçmem gerekiyor mu?" - Hayır.

Bir jeneratörle çalıştığımız için bu görev önemsiz

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

Bu, sürekli olarak bir seferde 1 rastgele sayıyı örnekleyecek, xasal olup olmadığını kontrol edecek, sonra ise geri dönecektir x. Bir asal bulunmadan önce sayılar listesi tükenirse NaNdöndürülür.


Not:

Bu cevap başlangıçta, bunun kopyası olarak kapatılan başka bir soruda paylaşıldı. Burada sunulan diğer çözümlerden çok farklı olduğu için burada da paylaşmaya karar verdim


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

A kullanmak Seten hızlı seçeneğinizdir. Bir geri arama oluşturucu kullanan benzersiz bir rastgele elde etmek için genel bir işlev. Şimdi hızlı ve tekrar kullanılabilir .

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

Bu, Fisher Yates / Durstenfeld Shuffle'ın bir uygulamasıdır , ancak gerçek bir dizi yaratılmadan, toplama boyutu mevcut elemanların sayısına kıyasla küçük olduğunda alan karmaşıklığını veya gereken belleği azaltır.

100'den 8 sayı seçmek için 100 elemanlık bir dizi oluşturmak gerekli değildir.

Bir dizinin oluşturulduğunu varsayarsak,

  • Dizinin (100) sonundan, rnd1'den 100'e kadar rastgele sayı ( ) alın
  • 100 ile rastgele sayıyı değiştirin rnd
  • 1. adımı dizi (99) ile tekrarlayın

Bir dizi oluşturulmazsa, gerçek değiştirilen konumları hatırlamak için bir hashMap kullanılabilir. Üretilen ikinci rasgele sayı, daha önce üretilen sayılardan birine eşit olduğunda, harita, gerçek değer yerine o konumdaki geçerli değeri sağlar.

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

Burada, 0 ile 100 aralığından (hem 0 hem de 100 dahil) alınan ve hiçbir çoğaltma yapılmadan rastgele 5 sayı örneği verilmiştir.

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

Bunu tek bir astarla da yapabilirsiniz:

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


Hiçbir şey vermemenin saflığı için.
Marcin Król
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.