Pertanyaan Hasilkan string / karakter acak di JavaScript


Saya ingin string 5 karakter yang terdiri dari karakter yang dipilih secara acak dari set [a-zA-Z0-9].

Apa cara terbaik untuk melakukan ini dengan JavaScript?


1151
2017-08-28 21:14


asal


Jawaban:


Saya pikir ini akan berhasil untuk Anda:

function makeid() {
  var text = "";
  var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

  for (var i = 0; i < 5; i++)
    text += possible.charAt(Math.floor(Math.random() * possible.length));

  return text;
}

console.log(makeid());


1637
2017-08-28 21:21



Math.random().toString(36).substring(7);

1726
2017-11-10 18:12



Math.random buruk untuk hal semacam ini

Pilihan 1

Jika Anda bisa melakukan ini serverdi samping, gunakan saja crypto modul

var crypto = require("crypto");
var id = crypto.randomBytes(20).toString('hex');

// "bb5dc8842ca31d4603d6aa11448d1654"

String yang dihasilkan akan dua kali lebih lama dari byte acak yang Anda hasilkan; setiap byte yang dikodekan ke hex adalah 2 karakter. 20 byte akan menjadi 40 karakter hex.


pilihan 2

Jika Anda harus melakukan ini klien-di samping, mungkin mencoba modul uuid

var uuid = require("uuid");
var id = uuid.v4();

// "110ec58a-a0f2-4ac4-8393-c866d813b8d1"

Opsi 3

Jika Anda harus melakukan ini klien-di samping dan Anda tidak perlu mendukung peramban lama, Anda dapat melakukannya tanpa ketergantungan

// dec2hex :: Integer -> String
function dec2hex (dec) {
  return ('0' + dec.toString(16)).substr(-2)
}

// generateId :: Integer -> String
function generateId (len) {
  var arr = new Uint8Array((len || 40) / 2)
  window.crypto.getRandomValues(arr)
  return Array.from(arr, dec2hex).join('')
}

console.log(generateId())
// "82defcf324571e70b0521d79cce2bf3fffccd69"

console.log(generateId(20))
// "c1a050a4cd1556948d41"


238
2018-01-02 19:18



Berikut ini peningkatannya jawaban yang sangat baik doubletap. Yang asli memiliki dua kekurangan yang dibahas di sini:

Pertama, seperti yang telah disebutkan orang lain, itu memiliki kemungkinan kecil menghasilkan string pendek atau bahkan string kosong (jika angka acak adalah 0), yang dapat merusak aplikasi Anda. Berikut ini solusinya:

(Math.random().toString(36)+'00000000000000000').slice(2, N+2)

Kedua, baik yang asli maupun solusi di atas membatasi ukuran string N hingga 16 karakter. Berikut ini akan mengembalikan string ukuran N untuk sembarang N (tetapi perhatikan bahwa menggunakan N> 16 tidak akan menambah keacakan atau mengurangi kemungkinan tabrakan):

Array(N+1).join((Math.random().toString(36)+'00000000000000000').slice(2, 18)).slice(0, N)

Penjelasan:

  1. Pilih nomor acak dalam rentang [0,1), yaitu antara 0 (inklusif) dan 1 (eksklusif).
  2. Konversikan angka ke string dasar-36, yaitu menggunakan karakter 0-9 dan a-z.
  3. Pad dengan nol (memecahkan masalah pertama).
  4. Potong bagian depan '0.' awalan dan tambahan nol bantalan.
  5. Ulangi string cukup kali untuk memiliki setidaknya karakter N di dalamnya (dengan Bergabung string kosong dengan string acak yang lebih pendek digunakan sebagai pemisah).
  6. Slice persis N karakter dari string.

Pemikiran lebih lanjut:

  • Solusi ini tidak menggunakan huruf besar, tetapi dalam hampir semua kasus (tidak dimaksudkan), itu tidak masalah.
  • Panjang string maksimum pada N = 16 dalam jawaban asli diukur dalam Chrome. Di Firefox itu N = 11. Tapi seperti yang dijelaskan, solusi kedua adalah tentang mendukung panjang string yang diminta, bukan tentang menambahkan keacakan, sehingga tidak membuat banyak perbedaan.
  • Semua string yang dikembalikan memiliki probabilitas yang sama untuk dikembalikan, setidaknya sejauh hasil yang dikembalikan oleh Math.random () terdistribusi secara merata (ini bukan keacakan kekuatan kriptografi, dalam hal apapun).
  • Tidak semua string ukuran yang mungkin N dapat dikembalikan. Dalam solusi kedua ini sudah jelas (karena string yang lebih kecil hanya diduplikasi), tetapi juga dalam jawaban asli ini benar karena dalam konversi ke basis-36 beberapa bit terakhir mungkin bukan bagian dari bit acak asli. Khususnya, jika Anda melihat hasil Math.random (). ToString (36), Anda akan melihat karakter terakhir tidak terdistribusi secara merata. Sekali lagi, dalam hampir semua kasus itu tidak masalah, tetapi kita memotong string terakhir dari awal daripada akhir string acak sehingga string pendek (misalnya N = 1) tidak terpengaruh.

Memperbarui:

Berikut adalah beberapa gaya satu garis fungsional lainnya yang saya temukan. Mereka berbeda dari solusi di atas dalam hal:

  • Mereka menggunakan alfabet sewenang-wenang eksplisit (lebih umum, dan cocok untuk pertanyaan asli yang meminta huruf besar dan huruf kecil).
  • Semua string dengan panjang N memiliki probabilitas yang sama untuk dikembalikan (yaitu string tidak mengandung pengulangan).
  • Mereka didasarkan pada fungsi peta, daripada trik toString (36), yang membuatnya lebih lugas dan mudah dimengerti.

Jadi, katakanlah alfabet pilihan Anda

var s = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

Kemudian keduanya setara satu sama lain, jadi Anda bisa memilih mana yang lebih intuitif untuk Anda:

Array(N).join().split(',').map(function() { return s.charAt(Math.floor(Math.random() * s.length)); }).join('');

dan

Array.apply(null, Array(N)).map(function() { return s.charAt(Math.floor(Math.random() * s.length)); }).join('');

Edit:

Sepertinya saya qubyte dan Martijn de Milliano muncul dengan solusi yang mirip dengan yang terakhir (pujian!), yang entah bagaimana saya lewatkan. Karena mereka tidak terlihat sekilas, saya akan meninggalkannya di sini untuk berjaga-jaga jika seseorang benar-benar menginginkan satu kalimat :-)

Juga, menggantikan 'Array baru' dengan 'Array' di semua solusi untuk memangkas beberapa byte lagi.


128
2017-11-13 21:18



Singkat, mudah, dan andal

Mengembalikan secara tepat 5 karakter acak, dibandingkan dengan beberapa jawaban berperingkat teratas yang ditemukan di sini.

Math.random().toString(36).substr(2, 5);

126
2017-07-27 20:24



Sesuatu seperti ini seharusnya berfungsi

function randomString(len, charSet) {
    charSet = charSet || 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    var randomString = '';
    for (var i = 0; i < len; i++) {
        var randomPoz = Math.floor(Math.random() * charSet.length);
        randomString += charSet.substring(randomPoz,randomPoz+1);
    }
    return randomString;
}

Panggilan dengan charset default [a-zA-Z0-9] atau kirim sendiri:

var randomValue = randomString(5);

var randomValue = randomString(5, 'PICKCHARSFROMTHISSET');

81
2017-08-28 21:28



function randomstring(L) {
  var s = '';
  var randomchar = function() {
    var n = Math.floor(Math.random() * 62);
    if (n < 10) return n; //1-10
    if (n < 36) return String.fromCharCode(n + 55); //A-Z
    return String.fromCharCode(n + 61); //a-z
  }
  while (s.length < L) s += randomchar();
  return s;
}
console.log(randomstring(5));


61
2017-08-29 02:41



Solusi paling ringkas, karena slice lebih pendek dari substring. Mengurangkan dari ujung string memungkinkan untuk menghindari simbol titik mengambang yang dihasilkan oleh random fungsi:

Math.random().toString(36).slice(-5);

atau bahkan

(+new Date).toString(36).slice(-5);

// Using Math.random
console.log(Math.random().toString(36).slice(-5));

// Using new Date
console.log((+new Date).toString(36).slice(-5));


48
2017-10-15 11:11



Random String Generator (Alpha-Numeric | Alpha | Numeric)

/**
 * RANDOM STRING GENERATOR
 *
 * Info:      http://stackoverflow.com/a/27872144/383904
 * Use:       randomString(length [,"A"] [,"N"] );
 * Default:   return a random alpha-numeric string
 * Arguments: If you use the optional "A", "N" flags:
 *            "A" (Alpha flag)   return random a-Z string
 *            "N" (Numeric flag) return random 0-9 string
 */
function randomString(len, an){
    an = an&&an.toLowerCase();
    var str="", i=0, min=an=="a"?10:0, max=an=="n"?10:62;
    for(;i++<len;){
      var r = Math.random()*(max-min)+min <<0;
      str += String.fromCharCode(r+=r>9?r<36?55:61:48);
    }
    return str;
}
randomString(10);        // "4Z8iNQag9v"
randomString(10, "A");   // "aUkZuHNcWw"
randomString(10, "N");   // "9055739230"

Selamat bersenang-senang. demo jsBin


Sementara di atas menggunakan pemeriksaan tambahan untuk output yang diinginkan (A / N, A, N), mari kita memecahnya menjadi hal-hal penting (hanya Alpha-Numeric) untuk pemahaman yang lebih baik:

  • Buat fungsi yang menerima argumen (panjang yang diinginkan dari hasil String acak)
  • Buat string kosong seperti var str = ""; untuk menggabungkan karakter acak
  • Di dalam satu lingkaran membuat rand nomor indeks dari 0 hingga 61 (0..9 + A..Z + a..z = 62)
  • Membuat logika kondisional untuk Sesuaikan / perbaiki rand (Karena itu 0..61) menambahnya dengan beberapa nomor (lihat contoh di bawah) untuk mendapatkan kembali hak CharCode nomor dan Karakter terkait.
  • Di dalam loop digabungkan ke str Sebuah String.fromCharCode( incremented rand )

Mari gambar itu Tabel karakter dan mereka rentang:

_____0....9______A..........Z______a..........z___________  Character
     | 10 |      |    26    |      |    26    |             Tot = 62 characters
    48....57    65..........90    97..........122           CharCode ranges

Math.floor( Math.random * 62 ) memberikan rentang dari 0..61 (apa yang kita butuhkan). Cara memperbaiki (increment) secara acak untuk mendapatkan yang benar rentang charCode?

      |   rand   | charCode |  (0..61)rand += fix            = charCode ranges |
------+----------+----------+--------------------------------+-----------------+
0..9  |   0..9   |  48..57  |  rand += 48                    =     48..57      |
A..Z  |  10..35  |  65..90  |  rand += 55 /*  90-35 = 55 */  =     65..90      |
a..z  |  36..61  |  97..122 |  rand += 61 /* 122-61 = 61 */  =     97..122     |

Itu operasi bersyarat logika dari tabel di atas:

   rand += rand>9 ? ( rand<36 ? 55 : 61 ) : 48 ;
// rand +=  true  ? (  true   ? 55 else 61 ) else 48 ;

Jika Anda mengikuti penjelasan di atas, Anda harus dapat membuat ini potongan alfa-numerik:

demo jsBin

function randomString( len ) {
  var str = "";                                         // String result
  for(var i=0; i<len; i++){                             // Loop `len` times
    var rand = Math.floor( Math.random() * 62 );        // random: 0..61
    var charCode = rand+= rand>9? (rand<36?55:61) : 48; // Get correct charCode
    str += String.fromCharCode( charCode );             // add Character to str
  }
  return str;       // After all loops are done, return the concatenated string
}

console.log( randomString(10) ); // "7GL9F0ne6t"

Atau jika Anda mau:

function randomString( n ) {
  var r="";
  while(n--)r+=String.fromCharCode((r=Math.random()*62|0,r+=r>9?(r<36?55:61):48));
  return r;
}

40
2018-01-10 02:09



Cara paling sederhana adalah:

(new Date%9e6).toString(36)

Ini menghasilkan string acak dari 5 karakter berdasarkan waktu saat ini. Contoh keluarannya 4mtxjatau 4mv90atau 4mwp1

Masalah dengan ini adalah bahwa jika Anda memanggilnya dua kali pada detik yang sama, itu akan menghasilkan string yang sama.

Cara yang lebih aman adalah:

(0|Math.random()*9e6).toString(36)

Ini akan menghasilkan string acak dari 4 atau 5 karakter, selalu berbeda. Contoh output seperti 30jzmatau 1r591atau 4su1a

Dalam kedua cara bagian pertama menghasilkan angka acak. Itu .toString(36) bagian melemparkan nomor ke representasi base36 (alphadecimal) dari itu.


27
2018-03-11 21:43



Versi yang lebih baru dengan es6  operator menyebar:

[...Array(30)].map(() => Math.random().toString(36)[3]).join('') 

  • Itu 30 adalah nomor acak, Anda dapat memilih berapa pun token yang Anda inginkan
  • Itu 36 adalah jumlah radix maksimum yang dapat Anda berikan numeric.toString (), yang artinya semua angka dan huruf kecil a-z
  • Itu 3 digunakan untuk memilih nomor 3 dari string acak yang terlihat seperti ini: "0.mfbiohx64i", kita bisa mengambil indeks apa pun setelahnya 0.

24
2017-11-26 13:17