Hasilkan string / karakter acak dalam JavaScript

1780

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?

Tom Lehman
sumber
48
Peringatan: Tidak ada jawaban yang memberikan true-randomhasil! Hanya mereka pseudo-random. Saat menggunakan string acak untuk perlindungan atau keamanan, jangan gunakan salah satu dari itu !!! Cobalah salah satu dari api ini: random.org
Ron van der Heijden
48
Math.random (). ToString (36) .replace (/ [^ az] + / g, '')
Muaz Khan
13
Silakan masukkan solusinya dalam solusi.
chryss
216
Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 5);
Friedrich
12
Catatan HTML5 webcrypto randomness API memberikan keacakan nyata.
mikemaccana

Jawaban:

2433

Saya pikir ini akan bekerja untuk Anda:

function makeid(length) {
   var result           = '';
   var characters       = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
   var charactersLength = characters.length;
   for ( var i = 0; i < length; i++ ) {
      result += characters.charAt(Math.floor(Math.random() * charactersLength));
   }
   return result;
}

console.log(makeid(5));

csharptest.net
sumber
117
Ini bagus untuk string pendek, tetapi berhati-hatilah, menggunakan +=string seperti ini menyebabkannya memiliki perilaku O (n ^ 2). Jika Anda ingin membuat string yang lebih panjang, Anda harus membuat array karakter individual dan bergabung bersama di akhir.
dan_waterworth
97
@dan_waterworth Mungkin tidak masalah dalam hampir semua kasus: codinghorror.com/blog/2009/01/…
Alex Reece
7
@dan_waterworth, Sebenarnya, +=seringkali lebih cepat karena beberapa alasan, bahkan digunakan di dalam loop - jsperf.com/join-vs-concatenation
Konrad Borowski
18
@JonathanPaulson Tunjukkan nomornya . Lihat komentar sebelumnya dengan tautan jsperf atau jsperf.com/sad-tragedy-of-microoptimization or sitepen.com/blog/2008/05/09/string-performance-an-analysis dll. Selain itu, pertanyaan ini hanya melibatkan 5 rangkuman .
Alex Reece
11
@codenamejames Tolong jangan gunakan ini dalam pengasinan kata sandi Anda. Itu hanya pseudo-acak tidak aman. Dengan asumsi Anda menggunakan Node (saya bahkan tidak yakin harus mulai dari mana jika Anda salting di sisi klien), gunakan cryptosaja.
Hydrothermal
2330

let r = Math.random().toString(36).substring(7);
console.log("random", r);

Catatan: Algoritma di atas memiliki kelemahan berikut:

  • Ini akan menghasilkan di mana saja antara 0 dan 6 karakter karena fakta bahwa trailing nol dihapus ketika meratakan floating point.
  • Ini sangat tergantung pada algoritma yang digunakan untuk merumuskan angka floating point, yang sangat kompleks. (Lihat kertas "Cara Mencetak Angka Titik Apung dengan Akurat" .)
  • Math.random()dapat menghasilkan output yang dapat diprediksi ("tampak acak" tetapi tidak benar-benar acak) tergantung pada implementasinya. String yang dihasilkan tidak cocok ketika Anda perlu menjamin keunikan atau ketidakpastian.
  • Bahkan jika itu menghasilkan 6 karakter acak yang seragam dan tidak dapat diprediksi, Anda dapat berharap untuk melihat duplikat setelah menghasilkan hanya sekitar 50.000 string, karena paradoks ulang tahun . (sqrt (36 ^ 6) = 46656)
doubletap
sumber
276
Math.random().toString(36).substr(2, 5), karena .substring(7)menyebabkannya lebih dari 5 karakter. Poin penuh, masih!
naga
81
@Scoop toStringMetode tipe angka dalam javascript mengambil parameter opsional untuk mengubah nomor menjadi basis yang diberikan. Jika Anda melewati dua, misalnya, Anda akan melihat nomor Anda terwakili dalam biner. Mirip dengan hex (basis 16), basis 36 menggunakan huruf untuk mewakili angka di luar 9. Dengan mengubah angka acak ke basis 36, Anda akan berakhir dengan sekelompok huruf dan angka yang tampaknya acak.
Chris Baker
76
Terlihat cantik tetapi dalam beberapa kasus ini menghasilkan string kosong! Jika pengembalian acak 0, 0,5, 0,25, 0,125 ... akan menghasilkan string kosong atau pendek.
gertas
67
@gertas Ini bisa dihindari dengan (Math.random() + 1).toString(36).substring(7);
George Reith
84
Guy, ini sebenarnya tidak berguna. Jalankan hanya 1000000 kali dan Anda biasanya mendapatkan sekitar 110000 kejadian berulang: nilai var = {}, i = 0, dupateCount = 0, val; while (i <1000000) {val = Math.random (). toString (36) .substring (7); if (nilai [val]) {dupateCount ++; } nilai [val] = 1; i ++; } console.log ("TOTAL DUPLICATES", duplicateCount);
hacklikecrack
463

Math.random buruk untuk hal semacam ini

Pilihan 1

Jika Anda dapat melakukan ini di sisi server , cukup gunakan modul kripto -

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 di sisi klien , mungkin coba modul uuid -

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

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

Opsi 3

Jika Anda harus melakukan ini di sisi klien dan Anda tidak harus mendukung browser lama, Anda dapat melakukannya tanpa ketergantungan -

// dec2hex :: Integer -> String
// i.e. 0-255 -> '00'-'ff'
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"


Untuk informasi lebih lanjut tentang crypto.getRandomValues -

Itu crypto.getRandomValues() Metode memungkinkan Anda mendapatkan nilai acak cryptographically kuat. Array yang diberikan sebagai parameter diisi dengan angka acak (acak dalam arti kriptografisnya).

Ini contoh konsol kecil -

> var arr = new Uint8Array(4) # make array of 4 bytes (values 0-255)
> arr
Uint8Array(4) [ 0, 0, 0, 0 ]

> window.crypto
Crypto { subtle: SubtleCrypto }

> window.crypto.getRandomValues()
TypeError: Crypto.getRandomValues requires at least 1 argument, but only 0 were passed

> window.crypto.getRandomValues(arr)
Uint8Array(4) [ 235, 229, 94, 228 ]

Untuk dukungan IE11, Anda dapat menggunakan -

(window.crypto || window.msCrypto).getRandomValues(arr)

Untuk jangkauan browser, lihat https://caniuse.com/#feat=getrandomvalues

Terima kasih
sumber
4
Persis. Meskipun UUID baik untuk menetapkan ID untuk suatu hal, menggunakannya sebagai serangkaian karakter acak bukanlah ide bagus untuk alasan ini (dan mungkin lainnya).
wmassingham
2
Tidak perlu .map()di Opsi 3. Array.from(arr, dec2hex).join('')=== Array.from(arr).map(dec2hex).join(''). Terima kasih telah memperkenalkan saya pada fitur-fitur ini :-)
Fred Gandt
6
Anda harus menyebutkan dalam jawaban bahwa opsi 2 juga membutuhkan node.js untuk bekerja, itu bukan javascript murni.
Esko
5
Meskipun lebih aman secara kriptografis, ini sebenarnya tidak memenuhi persyaratan pertanyaan karena hanya menghasilkan 0-9 dan af (Heksadesimal), dan bukan 0-9, az, AZ.
qJake
1
Bukankah requiremodul hanya dapat digunakan di sisi server?
aJetHorn
173

Singkat, mudah, dan andal

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

Math.random().toString(36).substr(2, 5);
Ringvee Perak
sumber
9
Bagaimana jika Math.random().toString(36)mengembalikan nomor dengan kurang dari 5 karakter?
Michael Litvin
3
Yah, itu dakwaan menarik dari @ Aperçu, saya tidak mengatakan bahwa saya menemukan solusi tetapi saya telah menggunakannya dalam proyek saya selama bertahun-tahun sekarang. Dan itu tidak ada hubungannya dengan komentar yang Anda sebutkan. Dan saya cukup yakin bahwa di SO yang penting adalah informasi yang paling berguna di tempat yang tepat dan bahkan jika sudah ada di tempat lain juga. Untungnya, sepertinya setidaknya 51 orang telah menemukan jawaban ini bermanfaat, terima kasih!
Silver Ringvee
3
Untuk menghindari string kosong dalam kasus Math.random () mengembalikan 0 Anda dapat menggunakanfunction getRandomString() { var result = ''; while (!result) result = Math.random().toString(36).substring(2); return result; };
mikep
5
@rinogo Math.random () dapat mengembalikan 0 tetapi tidak 1 developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
mikep
6
Saya menjalankan kode ini 1.000.000.000 kali dan masih tidak mendapatkan string kosong: jsfiddle.net/mtp5730r Saya akan mengatakan Anda cukup aman dari mendapatkan string kosong.
MacroMan
157

Berikut perbaikan pada jawaban doubletap ini sangat baik . Dokumen asli memiliki dua kelemahan yang dibahas di sini:

Pertama, seperti yang disebutkan orang lain, ia memiliki kemungkinan kecil untuk menghasilkan string pendek atau bahkan string kosong (jika angka acaknya adalah 0), yang dapat merusak aplikasi Anda. Ini solusinya:

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

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

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

Penjelasan:

  1. Pilih angka acak dalam kisaran [0,1), yaitu antara 0 (inklusif) dan 1 (eksklusif).
  2. Konversi angka menjadi string base-36, yaitu menggunakan karakter 0-9 dan az.
  3. Pad dengan nol (memecahkan masalah pertama).
  4. Potong pemimpin '0.' awalan dan nol bantalan tambahan.
  5. Ulangi string cukup kali untuk memiliki setidaknya N karakter di dalamnya (dengan Menggabungkan string kosong dengan string acak pendek yang digunakan sebagai pembatas).
  6. Potong persis N karakter dari string.

Pikiran lebih lanjut:

  • Solusi ini tidak menggunakan huruf besar, tetapi dalam hampir semua kasus (tidak ada kata pun 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 () didistribusikan secara merata (dalam hal apa pun, ini bukan keacakan kekuatan-kriptografi, dalam hal apa pun).
  • Tidak semua string ukuran N yang mungkin dapat dikembalikan. Dalam solusi kedua ini 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 tidak menjadi bagian dari bit acak asli. Khususnya, jika Anda melihat hasil Math.random (). ToString (36), Anda akan melihat bahwa karakter terakhir tidak terdistribusi secara merata. Sekali lagi, dalam hampir semua kasus itu tidak masalah, tetapi kami mengiris string terakhir dari awal daripada akhir string acak sehingga string pendek (misalnya N = 1) tidak terpengaruh.

Memperbarui:

Berikut adalah beberapa gaya-gaya lain yang saya buat. Mereka berbeda dari solusi di atas dalam hal:

  • Mereka menggunakan alfabet arbitrer eksplisit (lebih umum, dan cocok untuk pertanyaan asli yang meminta huruf besar dan 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 mudah dan mudah dimengerti.

Jadi, katakan alfabet pilihan Anda adalah

var s = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

Maka keduanya setara satu sama lain, sehingga Anda dapat memilih mana yang lebih intuitif bagi 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:

Saya sepertinya qubyte dan Martijn de Milliano datang dengan solusi yang mirip dengan yang terakhir (pujian!), Yang entah bagaimana saya lewatkan. Karena mereka tidak melihat sepintas sekilas, saya akan meninggalkannya di sini kalau-kalau seseorang benar-benar menginginkan satu-liner :-)

Juga, ganti 'Array baru' dengan 'Array' di semua solusi untuk mengurangi beberapa byte lagi.

amichair
sumber
Mengapa tidak menambahkan 1 saja? (Math.random()+1).toString(36).substring(7);
emix
Karena menambahkan 1 tidak menyelesaikan salah satu dari dua masalah yang dibahas di sini. Misalnya, (1) .toString (36) .substring (7) menghasilkan string kosong.
amichair
Menggunakan Math.random().toString(36).substring(2,7)memberikan hasil yang diharapkan yang lebih seperti.substring(2, n+2)
Joseph Rex
Array.apply(null, {length: 5}).map(function() { return s.charAt(Math.floor(Math.random() * s.length)); }).join('')
Muhammad Umer
Ini hebat, tetapi ketika dieksekusi di Firefox dengan N = 16, ~ 6 digit terakhir berakhir menjadi nol ... (Tapi itu memuaskan keinginan OP untuk 5 karakter acak.)
Edward Newell
128

Solusi paling ringkas, karena slicelebih pendek dari substring. Mengurangkan dari ujung string memungkinkan untuk menghindari simbol floating point yang dihasilkan oleh randomfungsi:

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

atau bahkan

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

Pembaruan: Menambahkan satu lagi pendekatan menggunakan btoametode:

btoa(Math.random()).slice(0, 5);
btoa(+new Date).slice(-7, -2);
btoa(+new Date).substr(-7, 5);

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

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

// Using Math.random and Base 64 (btoa):
console.log(btoa(Math.random()).slice(0, 5));

// Using new Date and Base 64 (btoa):
console.log(btoa(+new Date).slice(-7, -2));
console.log(btoa(+new Date).substr(-7, 5));

Valentin Podkamennyi
sumber
Math.random().toString(36).slice(-5);- Bagaimana jika Math.random()kembali 0.0?
x-ray
@ x-ray, Anda akan mendapatkan "0";)
Valentin Podkamennyi
2
Persis. ;) Dan jika Math.random()mengembalikan 0.5hasilnya "0.i". Tidak yakin apakah ada kasus tepi lainnya. Hanya ingin menunjukkan bahwa ini bukan jawaban yang benar untuk pertanyaan (5 karakter dari [a-zA-Z0-9]).
x-ray
2
@ x-ray, saya tidak akan mengatakan bahwa ini adalah jawaban yang benar, saya hanya mengatakan bahwa ini adalah versi ringkas dari jawaban @doubletap di atas. Saya pribadi menggunakan (+new Date + Math.random())untuk mencegah kasus ini. Bagaimanapun, terima kasih atas catatannya.
Valentin Podkamennyi
1
Ini. Saya tidak tahu mengapa jawaban lain memerlukan begitu banyak kode
john ktejik
100

Sesuatu seperti ini seharusnya bekerja

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

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

var randomValue = randomString(5);

var randomValue = randomString(5, 'PICKCHARSFROMTHISSET');
CaffGeek
sumber
Varian contoh di sini dapat ditemukan di sini: mediacollege.com/internet/javascript/number/random.html
David
1
mungkin juga hanya mengurangi lenlangsung dalam satu whilelingkaran
drzaus
Terima kasih, saya baru saja memposting di bawah ini variasi coffeescript dari contoh ini: stackoverflow.com/a/26682781/262379
Dinis Cruz
Jika ini akan digunakan secara publik, maka Anda mungkin harus menghapus vokal. Entropi yang sedikit kurang, tetapi jauh lebih aman karena Anda tidak dapat menghasilkan kata-kata yang dapat menyinggung orang. Itu sebabnya saya suka ini, karena saya bisa mengirim karakter saya sendiri. Kerja bagus.
Nate Bunney
Cukup hardcore, bekerja untuk saya, Terima kasih!
Zaki Mohammed
73

Versi yang lebih baru dengan operator penyebaran es6 :

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

  • Itu 30 adalah nomor arbitrer, Anda dapat memilih token yang Anda inginkan
  • Ini 36adalah nomor radix maksimum yang dapat Anda lewati ke numeric.toString () , yang artinya semua angka dan huruf kecil a
  • Ini 2digunakan untuk memilih indeks ke-3 dari string acak yang terlihat seperti ini:, "0.mfbiohx64i"kita bisa mengambil indeks apa pun setelah0.
Atau Duan
sumber
Bisakah Anda jelaskan? Terutama mengapa Anda memberikan 36 ke toString () dan mengapa Anda memilih elemen ke-3?
vuza
5
ini adalah solusi terbaik
menang
bagus, tetapi solusi ini tidak menyertakan karakter [AZ] sebagai pertanyaan yang diminta, hanya [a-z0-9]
Nahuel Greco
71

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

kennebec
sumber
Saya suka ini yang terbaik. Anda dapat dengan mudah memodifikasi untuk menerima parameter tambahan dan hanya mengembalikan num, lowerers, atau caps. Saya tidak berpikir gaya ultra-kompresi diperlukanwhile(s.length< L) s+= randomchar();
mastaBlasta
3
Juga while(L--)akan melakukannya
vsync
1
Lebih baik menggunakan yang lebih kuat 'A'.charCodeAt(0)daripada angka ajaib 55(dan juga untuk 61). Terutama karena, pada platform saya, angka ajaib yang kembali adalah 65. Kode itu juga akan mendokumentasikan diri dengan lebih baik.
Grumdrig
Saya membuat varian minification dioptimalkan (46 byte lebih kecil) dari implementasi Anda di sini: stackoverflow.com/a/52412162
Waruyama
Semoga berhasil men-debug @Waruyama itu. Itulah gunanya webpack!
Dylan Watson
61

Pembuat String Acak (Alpha-Numeric | Alpha | Numeric)

/**
 * Pseudo-random string generator
 * http://stackoverflow.com/a/27872144/383904
 * Default: return a random alpha-numeric string
 * 
 * @param {Integer} len Desired length
 * @param {String} an Optional (alphanumeric), "a" (alpha), "n" (numeric)
 * @return {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;
}

console.log(randomString(10));      // i.e: "4Z8iNQag9v"
console.log(randomString(10, "a")); // i.e: "aUkZuHNcWw"
console.log(randomString(10, "n")); // i.e: "9055739230"


Sementara di atas menggunakan pemeriksaan tambahan untuk A / N, A, N yang diinginkan output , mari kita pilah sampai ke esensi (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 lingkaran, buat randnomor indeks dari 0 hingga 61 (0..9 + A..Z + a..z = 62)
  • Buat logika kondisional untuk Menyesuaikan / memperbaikirand (karena 0..61) menambahkannya dengan beberapa nomor (lihat contoh di bawah) untuk mendapatkan kembali hak.CharCode nomor yang dan Karakter terkait.
  • Di dalam loop menyatu dengan str aString.fromCharCode( incremented rand )

Mari kita gambarkan rentang tabel Karakter ASCII :

_____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).
Mari kita perbaiki acak untuk mendapatkan rentang kode karakter yang benar :

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

The bersyarat operasi logika dari tabel di atas:

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

Dari penjelasan di atas, inilah cuplikan alpha-numeric yang dihasilkan :

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)); // i.e: "7GL9F0ne6t"

Atau jika Anda akan:

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

console.log(randomString(10))

Roko C. Buljan
sumber
33

Cara paling sederhana adalah:

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

Ini menghasilkan string acak 5 karakter berdasarkan waktu saat ini. Contoh output adalah 4mtxjatau 4mv90atau4mwp1

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 4 atau 5 karakter, selalu berbeda. Contoh outputnya seperti 30jzmatau 1r591atau4su1a

Dalam kedua cara bagian pertama menghasilkan angka acak. Bagian .toString(36)melemparkan nomor ke representasi base36 (alfabet).

MasqueradeCircus
sumber
Saya tidak yakin bagaimana ini menjawab pertanyaan; Ini adalah pertanyaan berusia 7 tahun dengan banyak jawaban yang valid. Jika Anda memilih untuk memberikan jawaban baru, Anda harus benar-benar berhati-hati untuk memastikan bahwa jawaban Anda dijelaskan dan didokumentasikan dengan baik.
Claies
1
Jika Anda menggunakan Date, kenapa tidak Anda gunakan saja seperti:(+new Date).toString(36)
seniorpreacher
Saya suka solusi bilangan acak Anda, tetapi 9e6 hanya memberi 9 juta kemungkinan dibandingkan 60,4 juta yang untuk 5 digit (36 ^ 5) sehingga Anda bisa menggantinya dengan (0|Math.random()*6.04e7).toString(36)untuk menutupinya.
Le Droid
1
Saya ingin string acak gondrong dengan rutin sesingkat mungkin (untuk demo kode) yang tidak perlu luar biasa secara kriptografis, hanya menghasilkan beberapa "bulu" acak visual yang bagus. Saya suka jawaban ini yang terbaik (yang ke-2), jadi terima kasih. Dua sen: Saya bisa mengalahkan itu untuk sesak dengan satu keystroke kurang, dan biasanya akan menghasilkan 13 karakter acak (tanpa periode): (Math.random()*1e20).toString(36).
Andrew Willems
satu keraguan yang saya miliki dengan jawaban ini adalah bahwa itu tidak akan menggunakan [AZ] yang kebetulan ada di pertanyaan awal.
user.friendly
22

Berikut adalah beberapa kalimat yang mudah. Ubah new Array(5)untuk mengatur panjangnya.

Termasuk 0-9a-z

new Array(5).join().replace(/(.|$)/g, function(){return ((Math.random()*36)|0).toString(36);})

Termasuk 0-9a-zA-Z

new Array(5).join().replace(/(.|$)/g, function(){return ((Math.random()*36)|0).toString(36)[Math.random()<.5?"toString":"toUpperCase"]();});
bendytree
sumber
20

Saya tahu semua orang sudah melakukannya dengan benar, tetapi saya merasa ingin mencoba yang ini dengan cara yang paling ringan (ringan pada kode, bukan CPU):

function rand(length, current) {
  current = current ? current : '';
  return length ? rand(--length, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz".charAt(Math.floor(Math.random() * 60)) + current) : current;
}

console.log(rand(5));

Dibutuhkan sedikit waktu untuk membungkus kepala Anda, tapi saya pikir itu benar-benar menunjukkan betapa mengagumkannya sintaks javascript.

Roderick
sumber
20
Jika Anda mencoba untuk membuat kode singkat, mengapa menulis current = current ? current : '';ketika Anda bisa menulis current = current || '';
CaffGeek
9
karena kita berbicara optimasi mikro di sini saya benar-benar akan menyarankan untuk melewatkan penugasan variabel sepenuhnya jika tidak perlu:current || (current = '');
Thomas Heymann
Mencoba optimasi mikro sambil menggunakan algoritma rekursif "bagus" tetapi pemborosan sumber daya tidak masuk akal :-) A untuk loop masih yang terbaik di Javascript dan mengalahkan rekursi waktu besar, sampai kemajuan yang sangat besar dalam kode optimisasi runtimes dibuat.
Mörre
17

Jika Anda menggunakan Lodash atau Underscore , maka sangat sederhana:

var randomVal = _.sample('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', 5).join('');
anggur
sumber
6
Lodash menggunakan_.sampleSize('asdfgh',5).join('')
marlo
2
Ini sebenarnya bukan solusi yang baik, karena per dokumen setiap karakter berasal dari indeks unik. Itu berarti itu tidak benar-benar acak, karena tidak ada karakter yang bisa / akan mengulangi.
random_user_name
16

Untuk memenuhi persyaratan [a-zA-Z0-9] dan panjang = 5 gunakan

btoa(Math.random()).substr(5, 5);

Huruf kecil, huruf besar, dan angka akan muncul.

Sergio Cabral
sumber
1
Saya kira, Math.random () dapat menghasilkan string base64 dengan terlalu sedikit karakter.
Leif
14

Jika ada yang tertarik dengan satu-liner (meskipun tidak diformat untuk kenyamanan Anda) yang mengalokasikan memori sekaligus (tetapi perhatikan bahwa untuk string kecil itu benar-benar tidak masalah) di sini adalah bagaimana melakukannya:

Array.apply(0, Array(5)).map(function() {
    return (function(charset){
        return charset.charAt(Math.floor(Math.random() * charset.length))
    }('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'));
}).join('')

Anda dapat mengganti 5dengan panjang string yang Anda inginkan. Terima kasih kepada @AriyaHidayat dalam posting ini untuk solusi untuk mapfungsi yang tidak bekerja pada array yang jarang dibuat oleh Array(5).

Martijn de Milliano
sumber
13
Setiap program javascript adalah 'satu-liner' jika Anda memformatnya
hacklikecrack
13

Inilah metode yang saya buat.
Ini akan membuat string yang berisi karakter huruf besar dan kecil.
Selain itu saya telah menyertakan fungsi yang akan membuat string alfanumerik juga.

Contoh kerja:
http://jsfiddle.net/greatbigmassive/vhsxs/ (hanya alfa)
http://jsfiddle.net/greatbigmassive/PJwg8/ (alfanumerik)

function randString(x){
    var s = "";
    while(s.length<x&&x>0){
        var r = Math.random();
        s+= String.fromCharCode(Math.floor(r*26) + (r>0.5?97:65));
    }
    return s;
}

Tingkatkan Juli 2015
Ini melakukan hal yang sama tetapi lebih masuk akal dan mencakup semua surat.

var s = "";
while(s.length<x&&x>0){
    v = Math.random()<0.5?32:0;
    s += String.fromCharCode(Math.round(Math.random()*((122-v)-(97-v))+(97-v)));
}
Adam
sumber
Dengan fungsi ini, Anda tidak akan pernah mendapatkan huruf besar lebih dari 'M' atau huruf kecil lebih kecil dari 'n'.
erkanyildiz
Betulkah? ooh! mungkin akan mengujinya lebih dari itu. Hmm, bagaimanapun, mengingat itu adalah string acak dan kami tidak benar-benar peduli huruf apa yang ada di dalamnya (selama mereka acak) maka masih melakukan apa yang kita inginkan untuk melakukan itu yang terpenting tetapi ya, akan memberikan tingkatkan, terima kasih.
Adam
12

Dengan asumsi Anda menggunakan underscorejs dimungkinkan untuk menghasilkan string acak secara elegan hanya dalam dua baris:

var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
var random = _.sample(possible, 5).join('');
tiktak
sumber
6
Ini akan membuat nilai yang dikembalikan memiliki semua karakter unik. Juga, panjang string dibatasi hingga panjang var mungkin.
Yefu
10
const c = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
const s = [...Array(5)].map(_ => c[~~(Math.random()*c.length)]).join('')
Nahuel Greco
sumber
Sederhana, solusi bersih
Mark Swardstrom
Ini layak mendapatkan +1 yang lebih besar
Walid Ammar
10

Algoritma yang cepat dan ditingkatkan. Tidak menjamin seragam (lihat komentar).

function getRandomId(length) {
    if (!length) {
        return '';
    }

    const possible =
        'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    let array;

    if ('Uint8Array' in self && 'crypto' in self && length <= 65536) {
        array = new Uint8Array(length);
        self.crypto.getRandomValues(array);
    } else {
        array = new Array(length);

        for (let i = 0; i < length; i++) {
            array[i] = Math.floor(Math.random() * 62);
        }
    }

    let result = '';

    for (let i = 0; i < length; i++) {
        result += possible.charAt(array[i] % 62);
    }

    return result;
}
yaroslav
sumber
2
Jawaban yang bagus, tetapi kemungkinannya tidak seragam. Ada 62 karakter yang mungkin dan crypto.getRandomValuesmengembalikan salah satu dari 256 nilai unik. Karena 256 tidak dibagi dengan 62, Anda akhirnya memiliki kemungkinan sedikit lebih tinggi untuk mendapatkan karakter AH. Saya pikir solusi terbaik adalah melakukan apa yang YouTube lakukan, dan hanya menambahkan 2 karakter tambahan (mungkin -dan _) ke rangkaian karakter. Ngomong-ngomong, kerja bagus - jawaban ini membutuhkan lebih banyak cinta :)
TeWu
menambahkan - dan _ adalah ide bagus karena akan memberi Anda set base64 aman-url-lengkap
cowbert
8

Masalah dengan respons terhadap pertanyaan "Saya perlu string acak" (dalam bahasa apa pun) praktis setiap solusi menggunakan spesifikasi primer cacat panjang string . Pertanyaan-pertanyaan itu sendiri jarang mengungkapkan mengapa string acak diperlukan, tetapi saya akan menantang Anda jarang membutuhkan string acak panjang, katakan 8. Apa yang Anda selalu butuhkan adalah sejumlah string unik , misalnya, untuk digunakan sebagai pengidentifikasi untuk beberapa tujuan.

Ada dua cara utama untuk mendapatkan string unik yang unik : secara deterministik (yang tidak acak) dan menyimpan / membandingkan (yang memberatkan). Apa yang kita lakukan? Kami menyerah hantu. Kami pergi dengan keunikan probabilistik sebagai gantinya. Yaitu, kami menerima bahwa ada beberapa (betapapun kecil) risiko bahwa string kami tidak akan menjadi unik. Di sinilah memahami probabilitas tabrakan dan entropi sangat membantu.

Jadi saya akan ulangi kebutuhan yang tidak berubah sebagai membutuhkan sejumlah string dengan risiko pengulangan yang kecil. Sebagai contoh nyata, katakanlah Anda ingin menghasilkan potensi 5 juta ID. Anda tidak ingin menyimpan dan membandingkan setiap string baru, dan Anda ingin mereka menjadi acak, sehingga Anda menerima risiko berulang. Sebagai contoh, katakanlah risiko kurang dari 1 dalam satu triliun peluang berulang. Jadi berapa panjang tali yang Anda butuhkan? Nah, pertanyaan itu tidak ditentukan karena tergantung pada karakter yang digunakan. Tapi yang lebih penting, ini salah arah. Yang Anda butuhkan adalah spesifikasi entropi string, bukan panjangnya. Entropi dapat secara langsung terkait dengan probabilitas pengulangan dalam sejumlah string. Panjang string tidak bisa.

Dan di sinilah perpustakaan seperti EntropyString dapat membantu. Untuk menghasilkan ID acak yang memiliki peluang kurang dari 1 dalam satu triliun untuk diulang dalam 5 juta string menggunakan entropy-string:

import {Random, Entropy} from 'entropy-string'

const random = new Random()
const bits = Entropy.bits(5e6, 1e12)

const string = random.string(bits)

"44hTNghjNHGGRHqH9"

entropy-stringmenggunakan set karakter dengan 32 karakter secara default. Ada set karakter yang telah ditentukan sebelumnya, dan Anda dapat menentukan karakter Anda sendiri juga. Misalnya, membuat ID dengan entropi yang sama seperti di atas tetapi menggunakan karakter hex:

import {Random, Entropy, charSet16} from './entropy-string'

const random = new Random(charSet16)
const bits = Entropy.bits(5e6, 1e12)

const string = random.string(bits)

"27b33372ade513715481f"

Perhatikan perbedaan panjang string karena perbedaan jumlah karakter dalam set karakter yang digunakan. Risiko pengulangan dalam jumlah string potensial yang ditentukan adalah sama. Panjang string tidak. Dan yang paling penting, risiko pengulangan dan potensi jumlah string adalah eksplisit. Tidak perlu lagi menebak dengan panjang tali.

langit dingo
sumber
7
function randomString (strLength, charSet) {
    var result = [];

    strLength = strLength || 5;
    charSet = charSet || 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';

    while (--strLength) {
        result.push(charSet.charAt(Math.floor(Math.random() * charSet.length)));
    }

    return result.join('');
}

Ini sebersih yang akan didapat. Itu juga cepat, http://jsperf.com/ay-random-string .

Gajus
sumber
Bagi saya ini selalu menghasilkan string acak dengan strLength - 1: - /
xanderiel
3
Beralih dari --strLengthke strLength--memperbaikinya untuk saya.
xanderiel
7

Anda dapat mengulang melalui array item dan menambahkannya secara berulang ke variabel string, misalnya jika Anda ingin urutan DNA acak:

function randomDNA(len) {
  len = len || 100
  var nuc = new Array("A", "T", "C", "G")
  var i = 0
  var n = 0
  s = ''
  while (i <= len - 1) {
    n = Math.floor(Math.random() * 4)
    s += nuc[n]
    i++
  }
  return s
}

console.log(randomDNA(5));

Andy
sumber
6

Saya tidak menemukan solusi bersih untuk mendukung karakter huruf kecil dan besar.

Huruf kecil hanya mendukung:

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

Membangun solusi untuk mendukung huruf kecil dan besar:

Math.random().toString(36).substr(2, 5).split('').map(c => Math.random() < 0.5 ? c.toUpperCase() : c).join('');

Ubah 5in substr(2, 5)untuk menyesuaikan dengan panjang yang Anda butuhkan.

ravishi
sumber
6

Satu liner:

Array(15).fill(null).map(() => Math.random().toString(36).substr(2)).join('')
// Outputs: 0h61cbpw96y83qtnunwme5lxk1i70a6o5r5lckfcyh1dl9fffydcfxddd69ada9tu9jvqdx864xj1ul3wtfztmh2oz2vs3mv6ej0fe58ho1cftkjcuyl2lfkmxlwua83ibotxqc4guyuvrvtf60naob26t6swzpil
Andrew
sumber
Untuk membuatnya lebih pendek, ubah argumen Array(15)ke nilai yang lebih kecil. Misalnya: Array(4).
Andrew
Saya sangat menyukai solusi ini, sederhana dan jelas. Ini menghasilkan 15 angka acak antara 0 dan 1, menghasilkan heksadesimal, dan kemudian menghapus dua karakter pertama. Akhirnya menggabungkan semuanya.
Siscia
5

Ini pasti berhasil

<script language="javascript" type="text/javascript">
function randomString() {
 var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz";
 var string_length = 8;
 var randomstring = '';
 for (var i=0; i<string_length; i++) {
  var rnum = Math.floor(Math.random() * chars.length);
  randomstring += chars.substring(rnum,rnum+1);
 }
 document.randform.randomfield.value = randomstring;
}
</script>
Vignesh
sumber
5

Bagaimana dengan sesuatu seperti ini: Date.now().toString(36) Tidak terlalu acak, tetapi pendek dan cukup unik setiap kali Anda menyebutnya.

Swergas
sumber
1
Sayangnya ini tidak akan unik, karena Date.now()hanya memiliki resolusi milidetik. Ketika dijalankan dalam satu loop sederhana, misalnya, Anda akan mendapatkan banyak duplikat. for (let i = 0; i < 10; ++i) { console.log(Date.now().toString(36)); }.
Nate
5

Karakter alfanumerik yang tidak peka huruf besar-kecil:

function randStr(len) {
  let s = '';
  while (s.length < len) s += Math.random().toString(36).substr(2, len - s.length);
  return s;
}

// usage
console.log(randStr(50));

Manfaat dari fungsi ini adalah Anda bisa mendapatkan string acak panjang yang berbeda dan memastikan panjang string.

Case Sensitive All Chars:

function randStr(len) {
  let s = '';
  while (len--) s += String.fromCodePoint(Math.floor(Math.random() * (126 - 33) + 33));
  return s;
}

// usage
console.log(randStr(50));

Karakter Kustom

function randStr(len, chars='abc123') {
  let s = '';
  while (len--) s += chars[Math.floor(Math.random() * chars.length)];
  return s;
}

// usage
console.log(randStr(50));
console.log(randStr(50, 'abc'));
console.log(randStr(50, 'aab')); // more a than b

Ali
sumber
Jawaban ini lebih cocok untuk kasus penggunaan saya. Akan lebih keren jika Anda bisa menambahkan var possibleseperti dalam jawaban yang diterima, sehingga hasil dari fungsi lebih dapat dikonfigurasi.
Denis.Sabolotni
4

Hasilkan string 10 karakter. Panjangnya diatur oleh parameter (default 10).

function random_string_generator(len) {
var len = len || 10;
var str = '';
var i = 0;

for(i=0; i<len; i++) {
    switch(Math.floor(Math.random()*3+1)) {
        case 1: // digit
            str += (Math.floor(Math.random()*9)).toString();
        break;

        case 2: // small letter
            str += String.fromCharCode(Math.floor(Math.random()*26) + 97); //'a'.charCodeAt(0));
        break;

        case 3: // big letter
            str += String.fromCharCode(Math.floor(Math.random()*26) + 65); //'A'.charCodeAt(0));
        break;

        default:
        break;
    }
}
return str;
}
ropsiU
sumber
4

Anda bisa menggunakan coderain . Itu perpustakaan untuk menghasilkan kode acak sesuai dengan pola yang diberikan. Gunakan #sebagai pengganti untuk karakter huruf besar dan kecil serta digit:

var cr = new CodeRain("#####");
console.log(cr.next());

Ada penampung lain seperti Auntuk huruf besar atau9 angka.

Yang mungkin berguna adalah panggilan itu .next() akan selalu memberi Anda hasil yang unik sehingga Anda tidak perlu khawatir tentang duplikat.

Berikut adalah aplikasi demo yang menghasilkan daftar kode acak unik .

Pengungkapan penuh: Saya penulis coderain.

Lukasz Wiktor
sumber
TIDAK TIDAK TIDAK - gunakan metode asli.