Hasilkan nomor acak unik antara 1 dan 100

99

Bagaimana saya bisa menghasilkan beberapa angka acak unik antara 1 dan 100 menggunakan JavaScript?

kotor
sumber
19
Tidak benar-benar menipu karena ini berfokus pada javascript.
sinting
2
@dotty baik tidak ada perbedaan penting antara melakukan ini di Javascript dan melakukannya dalam bahasa lain, tetapi saya tidak akan memilih untuk menutup.
Pointy
1
Saya juga tidak akan memilih untuk menutup. Ini cukup spesifik.
Josh Stodola
1
Ada cara lain yang lebih bersih untuk melakukan stackoverflow.com/questions/51898200/…
Huangism

Jawaban:

174

Misalnya: Untuk menghasilkan 8 angka acak unik dan menyimpannya ke dalam array, Anda cukup melakukan ini:

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

adam0101
sumber
15
Kode sebenarnya jauh lebih baik untuk pertanyaan seperti itu daripada kode pseudo;) (menghapus jawaban saya yang merupakan kodesemu ...)
Roman Starkov
3
O bisa dipetik; menggunakan var randomnumber = Math.ceil (Math.random () * 100)
Alsciende
9
-1: algoritma ini adalah pendekatan yang naif; itu sangat tidak efisien.
Frerich Raabe
40
Wow. Naif sepertinya agak kuat. Ini mungkin bukan solusi terbaik, tetapi sederhana, singkat, mudah untuk melihat apa yang terjadi, dan berjalan dalam parameter operasi yang dapat diterima untuk apa yang perlu diselesaikan. Ke tugas berikutnya. Kesempurnaan itu bagus, tapi 'selesai' lebih baik daripada 'sempurna'.
adam0101
4
Ada kemungkinan fungsi mengembalikan 0 dalam larik. Menurut tautan ini: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… , Math.random () Returns a random number between 0 (inclusive) and 1 (exclusive). Jika the Math.random()secara tidak sengaja mengembalikan 0, Math.ceil(0)juga 0, meskipun kemungkinannya rendah.
Qian Chen
43
  1. Mengisi array dengan angka 1 hingga 100.
  2. Kocok .
  3. Ambil 8 elemen pertama dari larik yang dihasilkan.
ЯegDwight
sumber
8
pasti lebih efisien untuk mengubah kode hanya untuk melakukan 8 pengocokan pertama? (dan kemudian ambil 8 elemen terakhir dari larik semi-acak)
kedua
1
Begitulah cara saya selalu melakukannya juga. Jadi jika saya menginginkan sepuluh baris acak dari file dengan banyak baris di dalamnya, saya lakukan randlines file | head -10.
tchrist
1
Saya pikir itu adalah jawaban yang tepat, karena mempertahankan gangguan probabilitas, yang tidak dapat diterima oleh jawaban yang diterima
roberto tomás
2
Bagaimana jika N = 10 ^ 12? Tidak terlalu efisien.
shinzou
2
@shinzou di dunia nyata Anda tidak akan mengurutkan 10 ^ 12 angka menggunakan JavaScript. Sebuah pertanyaan tirival membutuhkan jawaban yang sepele. Saya di sini bukan untuk mengatasi kelaparan dunia. Saya diperlengkapi dengan baik untuk melakukan itu, tetapi bukan itu pertanyaannya.
ЯegDwight
14

Hasilkan permutasi 100 angka dan kemudian pilih secara serial.

Gunakan Algoritma Knuth Shuffle (alias 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;

   }
}

KODE DISALIN DARI LINK.

EDIT :

Kode yang ditingkatkan:

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

Potensi masalah:

Misalkan kita memiliki larik 100 angka {misalnya [1,2,3 ... 100]} dan kita berhenti bertukar setelah 8 swap; maka sebagian besar larik waktu akan terlihat seperti {1,2,3,76,5,6,7,8, ... angka di sini akan diacak ... 10}.

Karena setiap angka akan ditukar dengan probabilitas 1/100 jadi prob. dari menukar 8 angka pertama adalah 8/100 sedangkan prob. dari menukar 92 lainnya adalah 92/100.

Tetapi jika kita menjalankan algoritma untuk array penuh maka kita yakin (hampir) setiap entri ditukar.

Jika tidak, kita akan menghadapi pertanyaan: 8 nomor yang mana yang harus dipilih?

Pratik Deoghare
sumber
5
Pendekatan ini benar tetapi kurang optimal: Anda dapat berhenti mengocok setelah delapan kali pertukaran, karena Anda hanya memerlukan delapan nomor acak. Kode di atas menukar seluruh larik (dalam skenario ini, 100 elemen).
Frerich Raabe
Kode tersebut dapat diperbaiki secara serius. Nilai pengembalian, efek samping dan penggunaan fungsi semuanya IMO benar-benar kabur. Mungkin jika Anda menulis fungsi yang menjawab masalah asli dengan tepat, menggunakan fungsi FisherYates Anda, itu akan lebih jelas.
Alsciende
1
Jawaban diperbarui dengan kode yang ditingkatkan. Juga, @Frerich Raabe: masalah berhenti setelah delapan swap disebutkan.
Pratik Deoghare
Algoritme Fisher-Yates Anda salah. r harus bergantung pada i. Lihat
jawaban
Ups maaf kesalahan saya yang mengerikan !! Penerapan Anda keren. Menyukai ini. +1. Tolong beri tahu saya jika ada hal lain yang salah. Terima kasih.
Pratik Deoghare
12

Solusi JS Modern menggunakan Set (dan rata-rata kasus O (n))

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

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

Alister
sumber
Mengapa O (n)? Tidak bisakah itu berputar untuk waktu yang sewenang-wenang?
Anthony Wieser
@AnthonyWieser Anda benar, kasus terburuk. Saya menyiratkan kasus rata-rata karena Set.add adalah o (1)
Alister
Saya pikir ini bisa menghasilkan 0 seperti jawaban saya dulu sebelum diubah menjadi penggunaanMath.floor(Math.random()*100) + 1
adam0101
Sangat keren untuk ditemukan Setdi JS! Namun, bukankah solusi ini akan menyebabkan pembangkitan angka yang tidak perlu sampai salah satu memenuhi persyaratan keunikan, terutama pada iterasi terakhir, jika 8 mendekati 100? Jadi saya pikir saya lebih suka jawaban yang juga elegan dengan di sortbawah ini.
Gilad Barner
10

Teknik di atas bagus jika Anda ingin menghindari perpustakaan, tetapi tergantung apakah Anda baik-baik saja dengan perpustakaan, saya sarankan memeriksa Peluang untuk menghasilkan hal-hal acak di JavaScript.

Secara khusus untuk menjawab pertanyaan Anda, menggunakan Chance semudah:

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

Penafian, sebagai penulis Chance, saya agak bias;)

Victor Quinn
sumber
Beri suara positif
jika saya ingin membuat kode (8 string alfanumerik acak) untuk kupon, yang harus unik, bagaimana cara melakukannya dengan Chance.js? catatan: kupon akan dibuat sesuai permintaan, jadi jumlah kode tidak terbatas
Oscar Yuandinata
@OscarYuandinata itu mudah, lakukan saja var codes = chance.unique(chance.string, 8)Jika Anda memerlukan kode yang ditarik dari kumpulan karakter tertentu, Anda dapat menentukannya seperti ini: di chance.unique(chance.string, 8, {pool: "abcd1234"})mana abcd1234 dapat berupa karakter apa pun yang Anda inginkan dalam kumpulan tersebut. Lihat chancejs.com/#string
Victor Quinn
@VictorQuinn, maaf saya tidak menjelaskannya dengan jelas. Maksud saya, kode kuponnya adalah 8 karakter string alfanumerik acak, bukan array 8 string alfanumerik acak. hahaha ..
Oscar Yuandinata
Oh @OscarYuandinata itu jauh lebih mudah heh chance.string({ length: 8 })dan jika Anda hanya ingin karakter tertentu muncul dalam string itu, chance.string({ pool: 'abcd1234', length: 8 })yang akan mengembalikan string 8 karakter acak dari karakter abcd1234, jadi misalnya "2c2c44bc" atau "331141cc"
Victor Quinn
8

Untuk menghindari pengocokan yang lama dan tidak dapat diandalkan, saya akan melakukan hal berikut ...

  1. Buat array yang berisi angka antara 1 dan 100, secara berurutan.
  2. Hasilkan nomor acak antara 1 dan 100
  3. Cari nomor di indeks ini dalam larik dan simpan di hasil Anda
  4. Hapus elemnt dari larik, membuatnya lebih pendek
  5. Ulangi dari langkah 2, tetapi gunakan 99 sebagai batas atas nomor acak
  6. Ulangi dari langkah 2, tetapi gunakan 98 sebagai batas atas nomor acak
  7. Ulangi dari langkah 2, tetapi gunakan 97 sebagai batas atas nomor acak
  8. Ulangi dari langkah 2, tetapi gunakan 96 sebagai batas atas nomor acak
  9. Ulangi dari langkah 2, tetapi gunakan 95 sebagai batas atas nomor acak
  10. Ulangi dari langkah 2, tetapi gunakan 94 sebagai batas atas nomor acak
  11. Ulangi dari langkah 2, tetapi gunakan 93 sebagai batas atas nomor acak

Voila - tidak ada nomor yang berulang.

Saya dapat memposting beberapa kode aktual nanti, jika ada yang tertarik.

Sunting: Ini mungkin pukulan kompetitif dalam diri saya tetapi, setelah melihat posting oleh @Alsciende, saya tidak bisa menahan untuk memposting kode yang saya janjikan.

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

belugabob
sumber
Tapi kemudian angka kedelapan Anda acak dari 1 sampai 92, bukan 1 sampai 100. Jika Anda harus memilih 90 angka, angka terakhir Anda hanya akan diambil dari 1 sampai 10, bukan?
adam0101
@ adam0101 Tidak, karena dia menghapus nomor saat mengambilnya. Jadi di langkah 5, hanya ada 99 angka di lariknya. @belugabob Anda tidak lebih efisien dari Knuth Shuffle. Bahkan, sambungannya mungkin lebih mahal daripada shuffle (yang sangat andal)
Alsciende
@ adam0101: Dia menghapus elemen yang dipilih dari array (lihat langkah 4 di atas), sehingga menghindari elemen apa pun yang dipilih dua kali. Dia kemudian menggunakan batas atas bawah untuk nomor acak berikutnya, hanya karena lariknya lebih pendek.
Frerich Raabe
@Alsciende, Ya - berpikir bahwa akan ada cara untuk melakukan ini secara lebih efisien menggunakan pengacakan, tetapi tidak sepenuhnya yakin. Untuk menghindari penghapusan item dari larik, cukup salin entri terakhir dari larik (asalkan itu bukan yang Anda pilih) ke dalam posisi yang Anda pilih.
belugabob
1
Alasan untuk tidak mengurangi nilai.length, adalah bahwa tidak ada jaminan bahwa penurunan panjang array tidak dilakukan dengan mengalokasikan kembali memori. Menggunakan maxIndex memiliki efek yang sama, dengan mengabaikan entri terakhir dalam larik, karena entri tersebut menjadi tidak relevan.
belugabob
8

Pendekatan lain adalah menghasilkan larik 100 item dengan angka naik dan mengurutkannya secara acak. Ini sebenarnya mengarah ke cuplikan yang sangat singkat dan (menurut saya) sederhana.

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

Felix Lemke
sumber
Ini adalah jawaban favorit saya dari semuanya. Entah kenapa hanya mendapat 6 suara. Elegan dan dengan kompleksitas yang baik (asalkan sortdiimplementasikan dengan baik, yang saya yakin itu).
Gilad Barner
3

Saya akan melakukan ini:

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;
Gumbo
sumber
3

Ini adalah fungsi yang sangat umum yang telah saya tulis untuk menghasilkan bilangan bulat unik / non-unik acak untuk sebuah array. Asumsikan parameter terakhir benar dalam skenario ini untuk jawaban ini.

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

Di sini 'tempObj' adalah objek yang sangat berguna karena setiap bilangan acak yang dihasilkan akan langsung memeriksa tempObj ini jika kunci itu sudah ada, jika belum, maka kita mengurangi i satu per satu karena kita perlu 1 operasi tambahan karena nomor acak saat ini sudah ada .

Dalam kasus Anda, jalankan perintah berikut

_arrayRandom(8, 1, 100, true);

Itu saja.

kaizer1v
sumber
apa yang akan terjadi jika saya ingin 0 disertakan? baris min = (min) ? min : 1,akan selalu mengembalikan 1. (jadi 0 tidak akan pernah dipilih)
TBE
Poin yang sangat bagus. :). Terima kasih, saya telah melakukan perubahan yang sesuai. Sekarang akan kembali bahkan jika Anda lulus dalam 0.
kaizer1v
2

Mengocok angka dari 1 hingga 100 adalah strategi dasar yang tepat, tetapi jika Anda hanya membutuhkan 8 angka yang diacak, tidak perlu mengocok 100 angka.

Saya tidak terlalu paham Javascript, tapi saya yakin mudah untuk membuat array 100 null dengan cepat. Kemudian, untuk 8 putaran, Anda menukar elemen ke-n dari array (n mulai dari 0) dengan elemen yang dipilih secara acak dari n + 1 hingga 99. Tentu saja, setiap elemen yang belum terisi berarti bahwa elemen tersebut benar-benar telah menjadi indeks asli ditambah 1, jadi itu mudah untuk dijadikan faktor. Ketika Anda selesai dengan 8 putaran, 8 elemen pertama dari array Anda akan memiliki 8 angka yang diacak.

Randal Schwartz
sumber
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);

lebih pendek dari jawaban lain yang pernah saya lihat

FFF
sumber
1

Algoritme permutasi yang sama dengan The Machine Charmer, tetapi dengan implementasi prototipe. Lebih cocok untuk sejumlah besar pilihan. Menggunakan tugas penghancuran js 1.7 jika tersedia.

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

Sunting: Sebuah proposisi lain, lebih cocok untuk sejumlah kecil pilihan, berdasarkan jawaban belugabob. Untuk menjamin keunikan, kami menghapus nomor yang dipilih dari larik.

// 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);
Alsciende
sumber
Implementasi rekursif yang bagus - Saya telah memposting alternatif, dalam jawaban saya, yang tidak menggunakan sambungan, karena saya merasa ini adalah kinerja yang dapat dihindari (Bukan berarti OP memiliki masalah dengan kinerja)
belugabob
Solusi Anda pintar, tapi aku tidak akan menggunakannya di saya Array # metode memilih karena saya tidak ingin ini memiliki unsur-unsurnya berjalan sekitar ketika aku mengembalikannya.
Alsciende
Larik mana yang tidak ingin Anda ubah, larik 1-100 asli atau hasilnya? Yang pertama seharusnya tidak masalah, karena ini adalah array yang berfungsi, dan yang terakhir akan, berdasarkan sifat kode, tetap keluar dalam urutan acak. Tidak begitu yakin bahwa saya memahami alasan Anda.
belugabob
Yang asli. Saya menerapkan metode pemilihan Array # umum, yang menurut saya berguna. Fungsi ini tidak tahu apakah ini adalah array yang berfungsi atau tidak. Untuk menjadi generik, itu tidak mengubah ini lebih dari yang diperlukan.
Alsciende
Tapi itu tetap mengubahnya, meski hanya sedikit, yang tidak bisa dihindari saat menggunakan teknik ini.
belugabob
1

untuk array dengan lubang seperti ini [,2,,4,,6,7,,] karena masalah saya adalah mengisi lubang ini. Jadi saya memodifikasinya sesuai kebutuhan saya :)

solusi yang dimodifikasi berikut berhasil untuk saya :)

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
Pulkit Chaudhri
sumber
1

Jawaban terbaik sebelumnya adalah jawaban oleh sje397. Anda akan mendapatkan nomor acak sebaik mungkin, secepat mungkin.

Solusi saya sangat mirip dengan solusinya. Namun, terkadang Anda menginginkan nomor acak dalam urutan acak, dan itulah mengapa saya memutuskan untuk memposting jawaban. Selain itu, saya memberikan fungsi umum.

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));
AndersTornkvist
sumber
1

Ini adalah versi ES6 saya yang saya buat bersama. Saya yakin ini bisa sedikit lebih terkonsolidasi.

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

Alex Mireles
sumber
0

Bagaimana jika menggunakan properti objek sebagai tabel hash ? Dengan cara ini skenario terbaik Anda adalah hanya mengacak 8 kali. Ini hanya akan efektif jika Anda menginginkan sebagian kecil dari kisaran angka. Ini juga jauh lebih sedikit memori intensif daripada Fisher-Yates karena Anda tidak perlu mengalokasikan ruang untuk larik.

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

Saya kemudian menemukan bahwa Object.keys (obj) adalah fitur ECMAScript 5 jadi di atas cukup banyak tidak berguna di internet sekarang. Jangan takut, karena saya membuatnya kompatibel dengan ECMAScript 3 dengan menambahkan fungsi tombol seperti ini.

if (typeof keys == "undefined") 
{ 
  var keys = function(obj) 
  {
    props=[];
    for (k in ht) if (ht.hasOwnProperty(k)) props.push(k);
    return props;
  }
}
Jonas Elfström
sumber
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
CPslashM
sumber
0

jika Anda membutuhkan lebih unik, Anda harus menghasilkan array (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;
}

kode di atas lebih cepat:
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]

MajidTaheri
sumber
0

Menambahkan versi lain yang lebih baik dari kode yang sama (jawaban diterima) dengan fungsi JavaScript 1.6 indexOf. Tidak perlu melakukan loop melalui seluruh array setiap kali Anda memeriksa duplikatnya.

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

Versi Javascript yang lebih lama masih dapat menggunakan versi di atas

PS: Mencoba menyarankan pembaruan ke wiki tetapi ditolak. Saya masih berpikir ini mungkin berguna untuk orang lain.

software.wikipedia
sumber
0

Ini adalah solusi pribadi saya:

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

Ini secara acak menghasilkan 8 nilai array unik (antara 0 dan 7), lalu menampilkannya menggunakan kotak peringatan.

Adam Atlas
sumber
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;
}

Saya pikir metode ini berbeda dari metode yang diberikan di sebagian besar jawaban, jadi saya pikir saya dapat menambahkan jawaban di sini (meskipun pertanyaan itu diajukan 4 tahun yang lalu).

Kami menghasilkan 100 nomor acak, dan menandai masing-masing nomor dengan nomor dari 1 hingga 100. Kemudian kami menyortir nomor acak yang ditandai ini, dan tag dikocok secara acak. Atau, sesuai kebutuhan dalam pertanyaan ini, seseorang dapat menghapus hanya dengan menemukan 8 teratas dari nomor acak yang diberi tag. Menemukan 8 item teratas lebih murah daripada menyortir seluruh larik.

Perlu dicatat di sini, bahwa algoritma pengurutan mempengaruhi algoritma ini. Jika algoritme pengurutan yang digunakan stabil, ada sedikit bias yang mendukung jumlah yang lebih kecil. Idealnya, kita ingin algoritma pengurutan tidak stabil dan bahkan tidak bias terhadap stabilitas (atau ketidakstabilan) untuk menghasilkan jawaban dengan distribusi probabilitas yang seragam secara sempurna.

Kartik Kale
sumber
0

Ini dapat menangani pembuatan hingga 20 digit nomor acak UNIK

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

masukkan deskripsi gambar di sini

jsFiddle

Nofi
sumber
0

Solusi ini menggunakan hash yang lebih berkinerja O (1) daripada memeriksa apakah berada dalam array. Ini memiliki pemeriksaan ekstra aman juga. Semoga membantu.

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))
RIdotCOM
sumber
0

Menerapkan ini sebagai generator membuatnya cukup bagus untuk digunakan. Perhatikan, implementasi ini berbeda dari implementasi yang mengharuskan seluruh larik input diacak terlebih dahulu.

sampleFungsi ini bekerja dengan malas, memberi Anda 1 item acak per iterasi hingga Nitem yang Anda minta. Ini bagus karena jika Anda hanya ingin 3 item dari daftar 1000 , Anda tidak perlu menyentuh 1000 item terlebih dahulu.

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

Saya memilih untuk menerapkan sampledengan cara yang tidak mengubah array input, tetapi Anda dapat dengan mudah membantah bahwa implementasi yang bermutasi lebih baik.

Misalnya, shufflefungsi tersebut mungkin ingin mengubah larik input asli. Atau Anda mungkin ingin mengambil sampel dari masukan yang sama di waktu yang berbeda, memperbarui masukan setiap saat.

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

samplebukan lagi fungsi murni karena mutasi input larik, tetapi dalam keadaan tertentu (ditunjukkan di atas) mungkin lebih masuk akal.


Alasan lain saya memilih generator daripada fungsi yang hanya mengembalikan array adalah karena Anda mungkin ingin melanjutkan pengambilan sampel hingga kondisi tertentu.

Mungkin saya ingin bilangan prima pertama dari daftar 1.000.000 bilangan acak.

  • "Berapa banyak yang harus saya sampel?" - Anda tidak perlu menentukan
  • "Apakah saya harus menemukan semua bilangan prima terlebih dahulu dan kemudian memilih bilangan prima acak?" - Nggak.

Karena kita bekerja dengan generator, tugas ini tidak terlalu rumit

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

Ini akan terus menerus mengambil sampel 1 bilangan acak pada satu waktu x,, periksa apakah bilangan prima, lalu kembalikan xjika bilangan tersebut. Jika daftar bilangan habis sebelum bilangan prima ditemukan, NaNdikembalikan.


catatan:

Jawaban ini awalnya dibagikan pada pertanyaan lain yang ditutup sebagai duplikat dari pertanyaan ini. Karena sangat berbeda dari solusi lain yang disediakan di sini, saya memutuskan untuk membagikannya di sini juga

Terima kasih
sumber
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
}
Oscar López
sumber
0

Menggunakan a Setadalah opsi tercepat Anda. Berikut adalah fungsi umum untuk mendapatkan acak unik yang menggunakan generator panggilan balik. Sekarang cepat dan dapat digunakan kembali .

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

Steven Spungin
sumber
0

Ini adalah implementasi Fisher Yates / Durstenfeld Shuffle , tetapi tanpa pembuatan larik yang sebenarnya sehingga mengurangi kompleksitas ruang atau memori yang dibutuhkan, ketika ukuran pilihan kecil dibandingkan dengan jumlah elemen yang tersedia.

Untuk memilih 8 angka dari 100, tidak perlu membuat larik yang terdiri dari 100 elemen.

Dengan asumsi sebuah array dibuat,

  • Dari akhir larik (100), dapatkan nomor acak ( rnd) dari 1 hingga 100
  • Tukar 100 dan nomor acak rnd
  • Ulangi langkah 1 dengan larik (99)

Jika sebuah array tidak dibuat, hashMap dapat digunakan untuk mengingat posisi yang sebenarnya ditukar. Ketika bilangan acak kedua yang dihasilkan sama dengan salah satu bilangan yang dihasilkan sebelumnya, peta memberikan nilai saat ini di posisi itu daripada nilai sebenarnya.

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

TheMaster
sumber
0

Berikut adalah contoh 5 angka acak yang diambil dari rentang 0 hingga 100 (termasuk 0 dan 100) tanpa duplikasi.

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)
gildniy
sumber
-1

Anda juga dapat melakukannya dengan satu liner seperti ini:

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

Marcin Król
sumber
Untuk kemurnian tidak menugaskan apapun.
Marcin Król