JavaScript'te rastgele dize / karakterler oluşturun


1780

Setten rastgele seçilmiş karakterlerden oluşan 5 karakterli bir dize istiyorum [a-zA-Z0-9].

Bunu JavaScript ile yapmanın en iyi yolu nedir?


48
Uyarı: Cevapların hiçbirinin true-randomsonucu yok! Onlar sadece pseudo-random. Koruma veya güvenlik için rastgele dizeler kullanırken bunlardan hiçbirini kullanmayın !!! Bu api'lerden
Ron van der Heijden

48
Math.random (). ToString (36) .replace (/ [^ az] + / g, '')
Muaz Han

13
Lütfen çözümü bir çözüme koyun.
chryss

216
Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 5);
Friedrich

12
Not HTML5 webcrypto rasgelelik API'sı gerçek rasgelelik sağlar.
mikemaccana

Yanıtlar:


2430

Bunun sizin için çalışacağını düşünüyorum:

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


117
Bu kısa dizeler için iyidir, ancak +=bunun gibi dizelerde kullanmanın O (n ^ 2) davranışına neden olmasına dikkat edin . Daha uzun dizeler oluşturmak istiyorsanız, tek tek karakterler dizisi oluşturmalı ve sonunda bir araya getirmelisiniz.
dan_waterworth

97
@dan_waterworth Muhtemelen hemen hemen hiçbir durumda önemli değil : codinghorror.com/blog/2009/01/…
Alex Reece

7
@dan_waterworth, Aslında, +=döngüler içinde bile kullanıldığında bazı nedenlerden dolayı genellikle daha hızlıdır - jsperf.com/join-vs-concatenation
Konrad Borowski

18
@JonathanPaulson Bana sayıları göster . Bir jsperf bağlantısı veya jsperf.com/sad-tragedy-of-microoptimization veya sitepen.com/blog/2008/05/09/string-performance-an-analysis vb. İle önceki yoruma bakın . Ayrıca, bu soru yalnızca 5 birleştirme içerir. .
Alex Reece

11
@codenamejames Lütfen bunu şifre tuzlama işleminizde kullanmayın. Güvenli değil sadece sahte rasgele. Düğüm kullandığınızı varsayarsak (istemci tarafında tuzluyorsanız nereden başlayacağınızdan bile emin değilim) cryptoyerine kullanın.
Hidrotermal

2330

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

Not: Yukarıdaki algoritma aşağıdaki zayıflıklara sahiptir:

  • Kayan noktaları dize ederken sondaki sıfırların kaldırılması nedeniyle 0 ila 6 karakter arasında herhangi bir yerde üretilir.
  • Dehşet verici derecede karmaşık olan kayan nokta sayılarını dizmek için kullanılan algoritmaya derinden bağlıdır. (Bkz. "Kayan Nokta Sayılarını Doğru Yazdırma" .)
  • Math.random()uygulamaya bağlı olarak öngörülebilir ("rastgele görünümlü" ancak gerçekten rastgele olmayan) çıktılar üretebilir. Benzersizliği veya öngörülemezliği garanti etmeniz gerektiğinde ortaya çıkan dize uygun değildir.
  • Düzgün rasgele, öngörülemeyen 6 karakter üretse bile, doğum günü paradoksu nedeniyle sadece yaklaşık 50.000 dize oluşturduktan sonra bir kopya görmeyi bekleyebilirsiniz . (sqrt (36 ^ 6) = 46656)

276
Math.random().toString(36).substr(2, 5), çünkü .substring(7)5 karakterden daha uzun olmasına neden olur. Tam puan, hala!
ejderha

81
@Scoop toStringJavascript'teki bir sayı türünün yöntemi, sayıyı belirli bir tabana dönüştürmek için isteğe bağlı bir parametre alır. Örneğin iki tanesini geçerseniz, numaranızın ikili olarak temsil edildiğini görürsünüz. Hex (taban 16) 'a benzer şekilde, taban 36, 9'un üzerindeki rakamları temsil etmek için harfleri kullanır. Rastgele bir sayıyı taban 36'ya dönüştürerek, görünüşte rastgele harfler ve sayılardan oluşan bir grupla sarılırsınız.
Chris Baker

76
Güzel görünüyor ama bazı durumlarda bu boş bir dize oluşturur! Rastgele 0, 0,5, 0,25, 0,125 ... döndürürse, boş veya kısa dizeyle sonuçlanır.
gertas

67
@gertas Bu kaçınabilirsiniz(Math.random() + 1).toString(36).substring(7);
George Reith

84
Guy, bu neredeyse işe yaramaz. Sadece 1000000 kez çalıştırın ve genellikle yaklaşık 110000 tekrarlama olayı elde edersiniz: var değerleri = {}, i = 0, duplicateCount = 0, val; (i <1000000) {val = Math.random (). toString (36) .substring (7); if (değerler [val]) {duplicateCount ++; } değerler [val] = 1; i ++; } console.log ("TOPLAM DÖKÜMANLAR", duplicateCount);
hacklikecrack

463

Math.random bu tür şeyler için kötü

seçenek 1

Bu sunucu tarafı yapabiliyorsanız , kripto modülünü -

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

// "bb5dc8842ca31d4603d6aa11448d1654"

Ortaya çıkan dize, oluşturduğunuz rasgele baytların iki katı kadar uzun olacaktır; onaltılık olarak kodlanan her bayt 2 karakterdir. 20 bayt, onaltılık 40 karakter olacaktır.


seçenek 2

Bu istemciyi yapmanız gerekiyorsa , belki uuid modülünü deneyin -

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

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

Seçenek 3

Bu istemciyi yapmanız gerekiyorsa ve eski tarayıcıları desteklemeniz gerekmiyorsa, bağımlılık olmadan yapabilirsiniz -

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


Hakkında daha fazla bilgi için crypto.getRandomValues -

crypto.getRandomValues()Yöntem şifrelenmiş güçlü ve rasgele değerleri elde etmenizi sağlar. Parametre olarak verilen dizi rastgele sayılarla (kriptografik anlamında rastgele) doldurulur.

İşte küçük bir konsol örneği -

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

IE11 desteği için şunları kullanabilirsiniz -

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

Tarayıcı kapsamı için bkz. Https://caniuse.com/#feat=getrandomvalues


4
Kesinlikle. Bir UUID, bir şeye kimlik atamak için iyi olsa da, rastgele karakterler dizesi olarak kullanmak bu (ve muhtemelen diğer) nedenlerden dolayı harika bir fikir değildir.
wmassingham

2
.map()Seçenek 3'te gerek yok . Array.from(arr, dec2hex).join('')=== Array.from(arr).map(dec2hex).join(''). Beni bu özelliklerle tanıştırdığın için teşekkürler :-)
Fred Gandt

6
Cevapta, seçenek 2'nin de çalışmak için node.js'ye ihtiyacı olduğunu belirtmelisiniz, saf javascript değildir.
Esko

5
Daha kriptografik olarak güvenli olmakla birlikte, bu aslında sorunun gereksinimlerini karşılamamaktadır, çünkü 0-9, az, AZ değil, yalnızca 0-9 ve af (Onaltılık) çıktı verir.
qJake

1
Is not requiremodül kullanılan sunucu tarafında olmak verebiliyoruz?
aJetHorn

173

Kısa, kolay ve güvenilir

Burada bulunan en yüksek puanlı yanıtların aksine, tam olarak 5 rastgele karakter döndürür.

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

9
Math.random().toString(36)5 karakterden az bir sayı döndürürse ne olur ?
Michael Litvin

3
Bu @ Aperçu'dan ilginç bir iddianame, çözümü icat ettiğimi söylemiyorum ama bunu yıllardır projelerimde kullanıyorum. Ve bahsettiğiniz yorumla hiçbir ilgisi yok. Ve SO'da önemli olan şeyin doğru yerde ve başka bir yerde zaten mevcut olsa bile en yararlı bilgi olduğundan eminim. Neyse ki, en az 51 adam bu cevabı yararlı buldular, hoş geldiniz!
Silver Ringvee

3
Math.random () 0 döndürürse boş dize function getRandomString() { var result = ''; while (!result) result = Math.random().toString(36).substring(2); return result; };
almaktan kaçınmak

5
@rinogo Math.random () 0 döndürür, ancak 1
döndüremez.

6
Bu kodu 1.000.000.000 kez çalıştırdım ve hala boş bir dize alamadım: jsfiddle.net/mtp5730r Boş bir dize almaktan oldukça güvenli olduğunu söyleyebilirim.
MacroMan

157

İşte doubletap'ın mükemmel cevabında bir gelişme . Orijinal belgenin burada ele alınan iki dezavantajı vardır:

Birincisi, diğerlerinin de belirttiği gibi, kısa dizeler veya hatta rastgele bir dizgi (rastgele sayı 0 ise) üretme olasılığı düşüktür, bu da uygulamanızı bozabilir. İşte bir çözüm:

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

İkincisi, hem orijinal hem de yukarıdaki çözüm N dizesini 16 karakterle sınırlar. Aşağıdakiler, herhangi bir N için N boyutunda bir dize döndürecektir (ancak N> 16 kullanmanın rasgeleliği artırmayacağını veya çarpışma olasılığını azaltmayacağını unutmayın):

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

Açıklama:

  1. [0,1) aralığında, yani 0 (dahil) ile 1 (hariç) arasında rastgele bir sayı seçin.
  2. Sayıyı base-36 dizesine dönüştürün, örneğin 0-9 ve az karakterlerini kullanarak.
  3. Sıfırlarla doldurma (ilk sorunu çözer).
  4. Baştaki '0'ı dilimleyin. ön ek ve ekstra dolgu sıfırları.
  5. İçinde en az N karakter olacak şekilde dizeyi tekrarlayın (boş dizeleri ayırıcı olarak kullanılan daha kısa rasgele dizeyle birleştirerek).
  6. Dizeden tam olarak N karakter dilimleyin.

Diğer düşünceler:

  • Bu çözüm büyük harf kullanmaz, ancak hemen hemen tüm durumlarda (cezalandırma amaçlı değildir) önemli değildir.
  • Orijinal yanıttaki N = 16 değerindeki maksimum dize uzunluğu Chrome'da ölçülür. Firefox'ta N = 11'dir. Ancak açıklandığı gibi, ikinci çözüm, herhangi bir dize uzunluğunu desteklemekle ilgilidir, rastgele eklemekle ilgili değildir, bu yüzden çok fazla fark yaratmaz.
  • Tüm döndürülen dizeler, en azından Math.random () tarafından döndürülen sonuçların eşit olarak dağıtıldığı kadar eşit bir şekilde döndürülme olasılığına sahiptir (bu, her durumda kriptografik güç rastgele değildir).
  • N boyutundaki tüm olası dizeler döndürülemez. İkinci çözümde bu açıktır (daha küçük dize basitçe kopyalandığından), ancak orijinal cevapta da bu doğrudur çünkü base-36'ya dönüşümde son birkaç bit orijinal rastgele bitlerin bir parçası olmayabilir. Özellikle, Math.random (). ToString (36) sonucuna bakarsanız, son karakterin eşit olarak dağıtılmadığını fark edeceksiniz. Yine, neredeyse tüm durumlarda önemli değil, ancak kısa dizelerin (örn. N = 1) etkilenmemesi için rastgele dizenin sonundan ziyade son dizgiyi dilimliyoruz.

Güncelleme:

İşte size geldiğim birkaç diğer fonksiyonel tarzda tek gömlek. Yukarıdaki çözümden farklıdırlar:

  • Açık bir keyfi alfabe kullanırlar (daha genel ve hem büyük hem de küçük harfler için sorulan orijinal soruya uygundur).
  • Tüm N uzunluk dizeleri eşit bir geri dönme olasılığına sahiptir (yani ipler tekrar içermez).
  • Bunlar, toString (36) hilesi yerine bir harita işlevine dayanır, bu da onları daha basit ve anlaşılması kolay hale getirir.

Yani, seçtiğiniz alfabenin

var s = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

O zaman bu ikisi birbirine eşdeğerdir, böylece hangisinin size daha sezgisel olduğunu seçebilirsiniz:

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

ve

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

Düzenle:

Qubyte ve Martijn de Milliano'ya benziyorum ben bir şekilde cevapsız ikincisi benzer (şeref!) Çözümleri, ile geldi. Bir bakışta kısa görünmedikleri için, birinin gerçekten tek astarlı olmasını istemesi durumunda yine de burada bırakacağım :-)

Ayrıca, birkaç bayt daha tıraş etmek için tüm çözümlerde 'yeni Dizi'yi' Dizi 'ile değiştirdi.


Neden sadece 1 eklemiyorsun? (Math.random()+1).toString(36).substring(7);
emix

Çünkü 1 eklemek, burada tartışılan iki konuyu da çözmez. Örneğin, (1) .toString (36) .substring (7) boş bir dize üretir.
amichair

Kullanmak Math.random().toString(36).substring(2,7)beklenen bir sonuç verir, bu da daha çok.substring(2, n+2)
Joseph Rex

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

Bu harika, ancak Firefox'ta N = 16 ile yürütüldüğünde, son ~ 6 hane sıfır oluyor ... (Ama OP'nin 5 rastgele karakter arzusunu tatmin ediyor.)
Edward Newell

127

En kompakt çözüm, çünkü slicedaha kısadır substring. Dizenin sonundan çıkarma, randomişlev tarafından oluşturulan kayan nokta sembolünün önlenmesine izin verir :

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

ya da

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

Güncelleme:btoa Yöntemi kullanarak bir yaklaşım daha eklendi :

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


Math.random().toString(36).slice(-5);- Ya Math.random()geri dönerse 0.0?
röntgen

@ x-ray, alacaksınız "0";)
Valentin Podkamennyi

2
Kesinlikle. ;) Ve Math.random()döndürürse 0.5sonuç olur "0.i". Başka kenar kutuları olup olmadığından emin değilim. Sadece bunun soruya doğru bir cevap olmadığını belirtmek istedim ([a-zA-Z0-9] 'dan 5 karakter).
x-ışını

2
@ x-ray, bunun doğru cevap olduğunu söylemeyeceğim, sadece bunun yukarıdaki @doubletap cevabının kompakt bir versiyonu olduğunu söylüyorum. Şahsen (+new Date + Math.random())bu davayı önlemek için kullanıyorum . Her neyse, not için teşekkürler.
Valentin Podkamennyi

1
Bu. Diğer cevapların neden bu kadar kod gerektirdiğini bilmiyorum
john ktejik

100

Böyle bir şey işe yaramalı

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

Varsayılan karakter setiyle [a-zA-Z0-9] arayın veya kendi gönderiniz:

var randomValue = randomString(5);

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

Burada bir örnek varyantını burada bulabilirsiniz: mediacollege.com/internet/javascript/number/random.html
David

1
sadece lenbir whiledöngü içinde doğrudan
azaltabilir

Teşekkürler, ben sadece bu örneğin bir coffeescript varyasyon altında yayınlanmıştır: stackoverflow.com/a/26682781/262379
Dinis Cruz

Bunlar kamuya açık olacaksa, muhtemelen ünlüleri çıkarmalısınız. Biraz daha az entropi, ancak insanları rahatsız edebilecek hiçbir kelime üretemediğiniz için çok daha güvenlidir. Bu yüzden kendi karakter dizilimde gönderebildiğim için bunu beğendim. Aferin.
Nate Bunney

Oldukça sert, benim için çalıştı, Teşekkürler!
Zaki Muhammed

73

Es6 spread operatörü ile daha yeni bir sürüm :

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

  • 30Keyfi sayı, istediğiniz herhangi bir belirteç uzunluğu alabilirsiniz olduğu
  • 36Eğer geçirebilirsiniz en radix sayısıdır numeric.toString () anlamına gelir, tüm numaraları ve az küçük harfleri
  • 2Şöyle rastgele dizesinden 3th indeksi almak için kullanılır: "0.mfbiohx64i"biz sonra herhangi endeksi sürebilir0.

Açıklayabilir misiniz? Özellikle neden 36'yı toString () öğesine geçiriyorsunuz ve neden 3. elemanı seçiyorsunuz?
vuza

5
Bu en iyi çözümdür
overcomer

güzel, ancak bu çözüm soru olarak [AZ] karakter içermiyor, sadece [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));


Bunu en çok sevdim. Fazladan parametreleri kabul etmek ve yalnızca sayı, alçaltma veya büyük harf döndürmek için kolayca değiştirebilirsiniz. Ultra sıkıştırılmış stilin gerekli olduğunu düşünmüyorumwhile(s.length< L) s+= randomchar();
mastaBlasta

3
Ayrıca while(L--)yapacak
vsync

1
'A'.charCodeAt(0)Sihirli sayı yerine daha sağlam kullanmak daha iyidir 55(ve aynı şekilde 61). Özellikle, platformumda zaten, geri dönen sihirli sayı 65. Bu kod kendi kendini daha iyi belgeleyecektir.
Grumdrig

Burada uygulamanızın
minimize

Bu hata ayıklamada iyi şanslar @Waruyama. Bu webpack ne için!
Dylan Watson

61

Rastgele Dize Oluşturucu (Alfa-Sayısal | Alfa | Sayısal)

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


Yukarıdakiler istenen A / N, A, N çıkışı için ek kontroller kullanıyor olsa da, daha iyi bir anlayış için onu temellere (sadece Alfa-Sayısal) ayıralım:

  • Bir bağımsız değişkeni kabul eden bir işlev oluşturun (rastgele String sonucunun istenen uzunluğu)
  • var str = "";Rastgele karakterleri birleştirmek gibi boş bir dize oluşturun
  • Bir döngü içinde 0 ila 61 arasında bir randdizin numarası oluşturun (0..9 + A..Z + a..z = 62)
  • Doğru sayıyı ve ilgili Karakteri geri almak için Ayarlamak / düzeltmek için (0..61 olduğu için) bir sayı kadar arttırarak (aşağıdaki örneklere bakın) bir koşullu mantık oluşturun .randCharCode
  • Döngünün içinde strbirString.fromCharCode( incremented rand )

ASCII Karakter tablosu aralıklarını hayal edelim :

_____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 )bir ara verir 0..61(ihtiyacımız olan şey).
Doğru charCode aralıklarını elde etmek için rastgele düzeltelim :

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

Koşullu işlem mantık tablo yukarıdan:

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

Yukarıdaki açıklamadan, sonuçta ortaya çıkan alfa-sayısal snippet :

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"

Veya şunları yapacaksanız:

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


33

En basit yol:

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

Bu, geçerli saate göre 5 karakterlik rastgele dizeler oluşturur. Örnek çıkışı 4mtxjya da 4mv90ya da4mwp1

Buradaki sorun, aynı saniyede iki kez çağırırsanız, aynı dizeyi üretmesidir.

Daha güvenli yol:

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

Bu, her zaman farklı olan 4 veya 5 karakterlik rastgele bir dize oluşturur. Örnek çıktı şuna benzer 30jzmveya 1r591veya4su1a

Her iki şekilde de ilk bölüm rastgele bir sayı üretir. .toString(36)Parçası bunun bir base36 (alphadecimal) gösterimi için sayı atama.


Bunun soruya nasıl cevap verdiğinden emin değilim; Bu, zaten geçerli olan birçok geçerli cevabı olan 7 yaşında bir sorudur. Yeni bir cevap vermeyi seçerseniz, cevabınızın iyi açıklandığından ve belgelendiğinden emin olmak için çok dikkatli olmalısınız.
Claies

1
Date kullanıyorsanız, neden sadece şu şekilde kullanmıyorsunuz:(+new Date).toString(36)
seniorpreacher

Rastgele sayı çözümünüzü beğendim, ancak 9e6, 60,4 milyondan 5 basamak (36 ^ 5) için sadece 9 milyon olasılık veriyor, böylece onu (0|Math.random()*6.04e7).toString(36)kapsayacak şekilde değiştirebilirsiniz.
Le Droid

1
Kriptografik olarak şaşırtıcı olması gerekmeyen mümkün olduğunca kısa bir rutin (bir kod demosu için) ile uzunca bir rastgele dize istedim, sadece bazı güzel rastgele görsel "kabartmak" üretmek. Bu cevabı en iyi şekilde beğeniyorum (2'niz), bu yüzden teşekkür ederim. Fikrimi söyleyeyim: Ben bir eksik tuş ile darlığı için yenebilir ve genellikle (bir süre olmadan) 13 rasgele karakterler üretecek: (Math.random()*1e20).toString(36).
Andrew Willems

Bu cevapla ilgili bir sorun, orijinal soruda olan [AZ] 'yi kullanmayacağıdır.
user.friendly

22

İşte bazı kolay tek gömlekler. new Array(5)Uzunluğu ayarlamak için değiştirin .

Dahil olmak üzere 0-9a-z

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

Dahil olmak üzere 0-9a-zA-Z

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

20

Herkesin zaten doğru olduğunu biliyorum, ama bu mümkün olan en hafif şekilde gitmek gibi hissettim (kod ışık, CPU değil):

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

console.log(rand(5));

Kafanızı sarmak biraz zaman alıyor, ancak bence gerçekten javascript'in sözdiziminin ne kadar harika olduğunu gösteriyor.


20
Kodu kısa tutmaya çalışıyorsanız, neden yazabileceğinizi current = current ? current : '';yazın current = current || '';
CaffGeek

9
burada mikro optimizasyon konuştuğumuz için aslında değişken atamayı tamamen gerekli değilse atlamayı öneririm:current || (current = '');
Thomas Heymann

"Güzel" ama kaynak israfı özyinelemeli algoritma kullanırken mikro optimizasyon denemek hiçbir anlam ifade etmiyor :-) Bir for döngüsü hala Javascript en iyisidir ve runtimes optimizasyon kodunda gerçekten büyük ilerlemeler yapılana kadar özyineleme büyük zaman yener.
Morre

17

Eğer kullanıyorsanız Lodash veya alt çizgi , o zaman çok basit:

var randomVal = _.sample('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', 5).join('');

6
Lodash kullanır_.sampleSize('asdfgh',5).join('')
marlo

2
Bu aslında iyi bir çözüm değildir, çünkü dokümanlar başına her karakter benzersiz bir dizinden gelmektedir. Bu, hiçbir karakterin tekrar edemeyeceği / tekrarlayamayacağı için gerçekten rastgele olmadığı anlamına gelir.
random_user_name

16

[A-zA-Z0-9] ve uzunluk = 5 gereksinimlerini karşılamak için

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

Küçük harfler, büyük harfler ve sayılar oluşur.


1
Sanırım, Math.random () çok az karakterli bir base64 dizesine yol açabilir.
Leif

14

Herhangi bir kişinin hafızayı bir kerede tahsis eden (ancak kolaylık sağlamak için biçimlendirilmemiş olmasına rağmen) bir astarla ilgilenmesi durumunda (ancak küçük dizeler için gerçekten önemli olmadığını unutmayın) burada nasıl yapılacağıdır:

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

İstediğiniz 5dizenin uzunluğuyla değiştirebilirsiniz . Bu yazıdaki @AriyaHidayat sayesinde mapfonksiyonun yarattığı seyrek dizi üzerinde çalışmayan çözüm için teşekkürler Array(5).


13
Her javascript programı, bu şekilde biçimlendirirseniz bir 'tek astarlı'
hacklikecrack

13

İşte oluşturduğum yöntem.
Hem büyük hem de küçük harf içeren bir dize oluşturur.
Ayrıca alfasayısal bir dize oluşturacak işlevi ekledim.

Çalışma örnekleri:
http://jsfiddle.net/greatbigmassive/vhsxs/ (yalnızca alfa)
http://jsfiddle.net/greatbigmassive/PJwg8/ (alfasayısal)

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

Temmuz 2015'i Yükselt
Bu aynı şeyi yapıyor ancak daha anlamlı ve tüm harfleri içeriyor.

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

Bu işlevle, asla 'M' harfinden büyük veya 'n' harfinden küçük bir harf alamazsınız.
erkanyildiz

Gerçekten mi? ooh! muhtemelen daha sonra test edecek. Hmm, ancak rastgele bir dize verildiği ve içinde hangi harflerin olduğunu umursamıyoruz (rastgele oldukları sürece) yine de yapmasını istediğimiz şeyi yapıyor, ancak önemli olan her şey, ancak evet, yükseltme, teşekkürler.
Adam

12

Kullanmak varsayarsak underscorejs o zarif sadece iki satır rasgele dize oluşturmak mümkündür:

var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
var random = _.sample(possible, 5).join('');

6
Bu, döndürülen değerin tüm benzersiz karakterlere sahip olmasını sağlar. Ayrıca, ipin uzunluğu mümkün olanın uzunluğu ile sınırlıdır.
Yefu

10
const c = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
const s = [...Array(5)].map(_ => c[~~(Math.random()*c.length)]).join('')

Basit, Temiz çözüm
Mark Swardstrom

Bu daha büyük bir +1 hak ediyor
Walid Ammar

10

Hızlı ve geliştirilmiş algoritma. Üniformayı garanti etmez (yorumlara bakın).

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

2
Harika bir cevap ama olasılık tek tip değil. 62 olası karakter vardır ve crypto.getRandomValues256 benzersiz değerden birini döndürür. 256, 62'ye bölünmediği için, AH karakterlerini alma olasılığınız biraz yüksektir. Bence en iyi çözüm YouTube'un yaptıklarını yapmak ve karakter grubuna 2 ek karakter (muhtemelen -ve _) eklemek. Her neyse, harika iş - bu cevap çok daha fazla sevgiye ihtiyaç duyuyor :)
TeWu

ekleme - ve _ harika bir fikir çünkü size tam url güvenli base64 setini
alacak

8

"Rastgele dizelere ihtiyacım var" sorularına (hangi dilde olursa olsun) yanıtlar ile ilgili sorun hemen hemen her çözüm dize uzunluğunun hatalı bir birincil belirtimini kullanır . Rasgele dizeleri ihtiyaç vardır neden soruları kendileri nadiren ortaya, ama nadiren kaçınılmaz bir ihtiyaç bazı sayıdır Ne 8. demek, bir uzunlukta rasgele dizeleri ihtiyaç sorun olur benzersiz dizeleri bazı amaçla tanımlayıcılar olarak kullanmak, örneğin,.

Kesinlikle benzersiz dizeler elde etmenin iki önde gelen yolu vardır : deterministik olarak (rastgele değil) ve depola / karşılaştır (zahmetli). Biz ne yaptık? Hayaleti bırakıyoruz. Onun yerine olasılıksal teklikle gidiyoruz . Yani, dizelerimizin benzersiz olmayacağı konusunda küçük (ancak küçük) bir risk olduğunu kabul ediyoruz. Çarpışma olasılığını ve entropiyi anlamak burada yardımcı olur.

Bu yüzden, değişmez ihtiyacı küçük bir tekrarlama riski olan bir dizi dizeye ihtiyaç duyduğu şeklinde yeniden ifade edeceğim. Somut bir örnek olarak, 5 milyon kimlik potansiyeli oluşturmak istediğinizi varsayalım. Her yeni dizeyi saklamak ve karşılaştırmak istemezsiniz ve rastgele olmasını istersiniz, bu nedenle tekrarlama riskini kabul edersiniz. Örneğin, bir trilyon tekrarlama şansında 1'den az bir risk olduğunu varsayalım. Peki, ne kadar uzunluğa ihtiyacınız var? Bu soru, kullanılan karakterlere bağlı olduğu için yeterince belirsiz. Ama daha da önemlisi, yanlış yönlendirilmiş. İhtiyacınız olan şey, dizelerin entropisinin uzunluğu değil bir spesifikasyonu. Entropi, bazı dizelerde tekrarlanma olasılığı ile doğrudan ilişkili olabilir. Dize uzunluğu olamaz.

EntropyString gibi bir kütüphane bu noktada yardımcı olabilir. 5 milyon dizede 1 trilyondan daha az tekrarlama şansına sahip rastgele kimlikleri kullanarak 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-stringvarsayılan olarak 32 karakterden oluşan bir karakter seti kullanır. Önceden tanımlanmış başka karakter setleri de vardır ve kendi karakterlerinizi de belirleyebilirsiniz. Örneğin, yukarıdaki gibi aynı entropiye sahip ancak onaltılık karakterler kullanan kimlikler oluşturma:

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

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

const string = random.string(bits)

"27b33372ade513715481f"

Kullanılan karakter kümesindeki toplam karakter sayısındaki farktan dolayı dize uzunluğu farkına dikkat edin. Belirtilen sayıda potansiyel dizede tekrarlama riski aynıdır. Dize uzunlukları değildir. Ve en önemlisi, tekrarlama riski ve potansiyel dizi sayısı açıktır. Dize uzunluğu ile artık tahmin yok.


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

Bu alacak kadar temiz. Ayrıca hızlı, http://jsperf.com/ay-random-string .


Benim için bu her zaman rastgele dizeler oluşturur strLength - 1: - /
xanderiel

3
Geçiş --strLengthiçin strLength--benim için düzeltmeleri o.
xanderiel

7

Bir öğe dizisi arasında döngü oluşturabilir ve örneğin rastgele bir DNA dizisi istiyorsanız, bunları bir dize değişkenine yinelemeli olarak ekleyebilirsiniz:

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


6

Hem küçük hem de büyük harfleri desteklemek için temiz bir çözüm bulamadım.

Yalnızca küçük harf desteği:

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

Küçük ve büyük harfleri desteklemek için bu çözümü temel alan:

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

İhtiyacınız olan uzunluğa ayarlamak için 5girişi değiştirin substr(2, 5).


6

Bir astar:

Array(15).fill(null).map(() => Math.random().toString(36).substr(2)).join('')
// Outputs: 0h61cbpw96y83qtnunwme5lxk1i70a6o5r5lckfcyh1dl9fffydcfxddd69ada9tu9jvqdx864xj1ul3wtfztmh2oz2vs3mv6ej0fe58ho1cftkjcuyl2lfkmxlwua83ibotxqc4guyuvrvtf60naob26t6swzpil

Kısaltmak için argümanı Array(15)daha küçük bir değere değiştirin. Ör: Array(4).
Andrew

Bu çözümü gerçekten çok basit ve açık seviyorum. 0 ile 1 arasında 15 rasgele sayı üretiyor, onaltılı üretiyor ve ilk iki karakteri kaldırıyor. Sonunda hepsini bir araya getiriyor.
Siscia

5

Bu kesinlikle işe yarıyor

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

5

Böyle bir şeye ne dersiniz: Date.now().toString(36) Çok rastgele değil, her seferinde kısa ve oldukça benzersiz.


1
Maalesef Date.now()milisaniye çözünürlüğü olduğu için bu benzersiz olmayacak . Örneğin, basit bir döngüde çalıştırıldığında çok sayıda kopya alırsınız. for (let i = 0; i < 10; ++i) { console.log(Date.now().toString(36)); }.
Nate

5

Büyük / Küçük Harfe Duyarsız Alfanümerik Karakterler:

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

Bu işlevin yararı, farklı uzunluktaki rastgele dizeyi alabilmeniz ve dizenin uzunluğunu garanti etmesidir.

Büyük / Küçük Harfe Duyarlı Tüm Karakterler:

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

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

Özel Karakterler

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


Bu cevap kullanım durumum için daha uygun. var possibleKabul edilen cevapta bir benzer ekleyebilmeniz harika olurdu , bu nedenle işlevin sonucu daha yapılandırılabilir.
Denis.Sabolotni

4

10 karakter uzunluğunda dize oluşturun. Uzunluk parametre ile ayarlanır (varsayılan 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;
}

4

Coderain kullanabilirsiniz . Verilen desene göre rastgele kodlar oluşturmak için bir kütüphane. #Büyük ve küçük harfler ve rakamlar için yer tutucu olarak kullanın :

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

ABüyük harfler veya 9rakamlar gibi başka yer tutucular da vardır .

Yararlı olabilecek şey, .next() size her zaman benzersiz bir sonuç vereceğidir, böylece kopyalar hakkında endişelenmenize gerek yoktur.

İşte benzersiz rastgele kodların bir listesini üreten bir demo uygulaması .

Tam açıklama: Ben Coderain yazarım.


HAYIR HAYIR HAYIR - yerel yöntemleri kullanın.
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.