Generuj losowy ciąg / znaki w JavaScript


1777

Chcę ciąg 5 znaków złożony ze znaków wybranych losowo ze zbioru [a-zA-Z0-9].

Jak najlepiej to zrobić za pomocą JavaScript?


48
Ostrzeżenie: Żadna z odpowiedzi nie przyniosła true-randomrezultatu! Oni są tylko pseudo-random. Używając losowych ciągów do ochrony lub bezpieczeństwa, nie używaj żadnego z nich !!! Wypróbuj jeden z tych interfejsów API: random.org
Ron van der Heijden

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

13
Proszę umieścić rozwiązanie w rozwiązaniu.
chryss 24.09.2013

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

12
Uwaga Interfejs API losowości webcrypto HTML5 zapewnia prawdziwą losowość.
mikemaccana

Odpowiedzi:


2430

Myślę, że to zadziała dla ciebie:

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
Jest to dobre w przypadku krótkich ciągów, ale uwaga: użycie +=na takich ciągach powoduje, że ma zachowanie O (n ^ 2). Jeśli chcesz tworzyć dłuższe ciągi, powinieneś utworzyć tablicę pojedynczych znaków i połączyć je razem na końcu.
dan_waterworth

97
@dan_waterworth Prawdopodobnie w żadnym wypadku nie ma to znaczenia : codinghorror.com/blog/2009/01/…
Alex Reece

7
@dan_waterworth, Właściwie +=jest często z jakiegoś powodu szybszy, nawet używany wewnątrz pętli - jsperf.com/join-vs-concatenation
Konrad Borowski

18
@JonathanPaulson Pokaż mi liczby . Zobacz poprzedni komentarz z linkiem jsperf lub jsperf.com/sad-tragedy-of-microoptimization lub sitepen.com/blog/2008/05/09/string-performance-an-analysis itp. To pytanie obejmuje tylko 5 konkatenacji .
Alex Reece,

11
@codenamejames Proszę nie używać tego do solenia hasła. Jest tylko pseudolosowy, nie jest bezpieczny. Zakładając, że używasz Węzła (nie jestem nawet pewien, od czego zacząć, jeśli solisz po stronie klienta), użyj cryptozamiast tego.
Hydrotermalny,

2330

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

Uwaga: powyższy algorytm ma następujące słabości:

  • Wygeneruje gdziekolwiek od 0 do 6 znaków ze względu na fakt, że końcowe zera są usuwane podczas łączenia zmiennoprzecinkowych.
  • Zależy to głęboko od algorytmu stosowanego do struwania liczb zmiennoprzecinkowych, co jest przerażająco złożone. (Zobacz artykuł „Jak dokładnie drukować liczby zmiennoprzecinkowe” .)
  • Math.random()może generować przewidywalny („wyglądający losowo”, ale nie tak naprawdę losowy) wynik w zależności od implementacji. Powstały ciąg nie jest odpowiedni, gdy trzeba zagwarantować niepowtarzalność lub nieprzewidywalność.
  • Nawet jeśli wyprodukuje 6 jednorodnie losowych, nieprzewidywalnych postaci, możesz spodziewać się duplikatu po wygenerowaniu zaledwie około 50 000 ciągów, z powodu paradoksu urodzinowego . (sqrt (36 ^ 6) = 46656)

276
Math.random().toString(36).substr(2, 5), ponieważ .substring(7)powoduje, że ma on więcej niż 5 znaków. Nadal pełne punkty!
smok

81
@Scoop toStringMetoda typu liczbowego w javascript pobiera opcjonalny parametr do konwersji liczby na daną bazę. Jeśli na przykład zdasz dwa, zobaczysz, że Twój numer jest reprezentowany w postaci binarnej. Podobnie jak hex (podstawa 16), podstawa 36 używa liter do reprezentowania cyfr poza 9. Przekształcając liczbę losową na podstawę 36, skończysz z wiązką pozornie losowych liter i cyfr.
Chris Baker

76
Wygląda pięknie, ale w kilku przypadkach generuje to pusty ciąg! Jeśli losowe zwraca 0, 0,5, 0,25, 0,125 ... spowoduje pusty lub krótki ciąg.
gertas

67
@gertas Tego można uniknąć(Math.random() + 1).toString(36).substring(7);
George Reith,

84
Facet, to jest praktycznie bezużyteczne. Uruchom go tylko 1000000 razy, a na ogół otrzymasz około 110000 powtórzeń: var values ​​= {}, i = 0, duplicateCount = 0, val; while (i <1000000) {val = Math.random (). toString (36) .sstrstring (7); if (wartości [val]) {duplicateCount ++; } wartości [val] = 1; i ++; } console.log („TOTAL DUPLICATES”, duplicateCount);
hacklikecrack

463

Math.random jest zły dla tego rodzaju rzeczy

opcja 1

Jeśli możesz zrobić to po stronie serwera , po prostu użyj modułu kryptograficznego -

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

// "bb5dc8842ca31d4603d6aa11448d1654"

Wynikowy ciąg będzie dwa razy dłuższy niż generowane losowe bajty; każdy bajt zakodowany w postaci szesnastkowej ma 2 znaki. 20 bajtów będzie 40 znakami szesnastkowymi.


Opcja 2

Jeśli musisz zrobić to po stronie klienta , być może spróbuj modułu uuid -

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

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

Opcja 3

Jeśli musisz to zrobić po stronie klienta i nie musisz obsługiwać starych przeglądarek, możesz to zrobić bez zależności -

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


Aby uzyskać więcej informacji na temat crypto.getRandomValues-

Ta crypto.getRandomValues()metoda pozwala uzyskać kryptograficznie silne losowe wartości. Tablica podana jako parametr jest wypełniona liczbami losowymi (losowymi w znaczeniu kryptograficznym).

Oto mały przykład konsoli -

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

Do obsługi IE11 możesz użyć -

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

Aby zapoznać się z zasięgiem przeglądarki, patrz https://caniuse.com/#feat=getrandomvalues


4
Dokładnie. Chociaż identyfikator UUID jest odpowiedni do przypisania identyfikatora do rzeczy, użycie go jako ciągu losowych znaków nie jest dobrym pomysłem z tego (i prawdopodobnie innych) powodów.
wmassingham

2
Nie ma potrzeby .map()w opcji 3. Array.from(arr, dec2hex).join('')=== Array.from(arr).map(dec2hex).join(''). Dziękujemy za
zapoznanie się

6
Powinieneś wspomnieć w odpowiedzi, że opcja 2 wymaga również node.js do działania, to nie jest czysty JavaScript.
Esko

5
Chociaż jest bardziej kryptograficznie bezpieczny, nie spełnia wymagań pytania, ponieważ wypisuje tylko 0-9 i af (szesnastkowy), a nie 0-9, az, AZ.
qJake

1
Czy requiremoduł nie może być używany tylko po stronie serwera?
aJetHorn

173

Krótko, łatwo i niezawodnie

Zwraca dokładnie 5 losowych znaków, w przeciwieństwie do niektórych najwyżej ocenianych odpowiedzi tutaj.

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

9
Co jeśli Math.random().toString(36)zwróci liczbę składającą się z mniej niż 5 znaków?
Michael Litvin

3
Cóż, to ciekawe oskarżenie @ Aperçu, nie mówię, że wymyśliłem rozwiązanie, ale używam go w swoich projektach od lat. I nie ma to nic wspólnego z wspomnianym komentarzem. I jestem całkiem pewien, że w SO liczy się najbardziej użyteczna informacja we właściwym miejscu, a nawet jeśli już istnieje w innym miejscu. Na szczęście wydaje się, że co najmniej 51 osób uznało tę odpowiedź za przydatną, nie ma za co!
Srebrny Ringvee,

3
Aby uniknąć pustego łańcucha w przypadku, gdy Math.random () zwraca 0, możesz użyćfunction getRandomString() { var result = ''; while (!result) result = Math.random().toString(36).substring(2); return result; };
mikep

5
@rinogo Math.random () może zwrócić 0, ale nie 1 developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
mikep

6
Uruchomiłem ten kod 1 000 000 000 razy i nadal nie otrzymałem pustego ciągu: jsfiddle.net/mtp5730r Powiedziałbym, że jesteś całkiem bezpieczny przed otrzymaniem pustego ciągu.
MacroMan

157

Oto poprawa doskonałej odpowiedzi doubleletap . Oryginał ma dwie wady, które są tutaj omówione:

Po pierwsze, jak wspomnieli inni, ma małe prawdopodobieństwo wytworzenia krótkich lub nawet pustych łańcuchów (jeśli liczba losowa to 0), co może zepsuć twoją aplikację. Oto rozwiązanie:

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

Po drugie, zarówno oryginał, jak i powyższe rozwiązanie ograniczają rozmiar ciągu N do 16 znaków. Poniższe zwróci ciąg o rozmiarze N dla dowolnego N (ale należy pamiętać, że użycie N> 16 nie zwiększy losowości ani nie zmniejszy prawdopodobieństwa kolizji):

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

Wyjaśnienie:

  1. Wybierz liczbę losową z zakresu [0,1), tj. Od 0 (włącznie) do 1 (wyłącznie).
  2. Konwertuj liczbę na łańcuch podstawowy 36, tzn. Używając znaków 0–9 i az.
  3. Pad z zerami (rozwiązuje pierwszy problem).
  4. Odetnij wiodące „0” przedrostek i dodatkowe zera dopełniające.
  5. Powtórz ciąg wystarczająco długo, aby mieć w nim co najmniej N znaków (łącząc puste ciągi z krótszym ciągiem losowym używanym jako separator).
  6. Pokrój dokładnie N znaków z ciągu.

Dalsze przemyślenia:

  • W tym rozwiązaniu nie stosuje się wielkich liter, ale w prawie wszystkich przypadkach (bez zamierzonej gry słów) nie ma to znaczenia.
  • Maksymalna długość łańcucha przy N = 16 w pierwotnej odpowiedzi jest mierzona w Chrome. W Firefoksie jest to N = 11. Ale jak wyjaśniono, drugie rozwiązanie dotyczy obsługi dowolnej żądanej długości łańcucha, a nie dodawania losowości, więc nie robi to dużej różnicy.
  • Wszystkie zwrócone ciągi mają jednakowe prawdopodobieństwo, że zostaną zwrócone, przynajmniej w takim stopniu, w jakim wyniki zwrócone przez Math.random () są równomiernie rozmieszczone (w każdym razie nie jest to losowość siły kryptograficznej).
  • Nie wszystkie możliwe ciągi o rozmiarze N mogą zostać zwrócone. W drugim rozwiązaniu jest to oczywiste (ponieważ mniejszy ciąg jest po prostu powielany), ale również w pierwotnej odpowiedzi jest to prawdą, ponieważ w konwersji do bazy 36 ostatnie kilka bitów może nie być częścią oryginalnych losowych bitów. W szczególności, jeśli spojrzysz na wynik Math.random (). ToString (36), zauważysz, że ostatni znak nie jest równomiernie rozłożony. Ponownie, w prawie wszystkich przypadkach nie ma to znaczenia, ale przecinamy ostatni ciąg od początku zamiast końca losowego ciągu, aby nie wpływać na krótkie ciągi (np. N = 1).

Aktualizacja:

Oto kilka innych funkcjonalnych stylów, które wymyśliłem. Różnią się od powyższego rozwiązania tym, że:

  • Używają wyraźnego, arbitralnego alfabetu (bardziej ogólnego i odpowiedniego dla pierwotnego pytania, które wymagało zarówno wielkich, jak i małych liter).
  • Wszystkie ciągi o długości N mają jednakowe prawdopodobieństwo zwrotu (tzn. Ciągi nie zawierają powtórzeń).
  • Opierają się one na funkcji mapy, a nie na sztuczce toString (36), co czyni je prostszymi i łatwiejszymi do zrozumienia.

Powiedzmy, że twoim alfabetem jest

var s = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

Te dwa są sobie równe, więc możesz wybrać, który z nich jest bardziej intuicyjny:

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

i

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

Edytować:

Wygląda na to, że qubyte i Martijn de Milliano wymyślili rozwiązania podobne do tych drugich (kudos!), Których jakoś przegapiłem. Ponieważ na pierwszy rzut oka nie wyglądają tak krótko, zostawię to tutaj, na wypadek, gdyby ktoś naprawdę chciał mieć liniówkę :-)

Ponadto zastąpiono „new Array” „Array” we wszystkich rozwiązaniach, aby zmniejszyć liczbę kolejnych bajtów.


Dlaczego nie dodać 1? (Math.random()+1).toString(36).substring(7);
emix

Ponieważ dodanie 1 nie rozwiązuje żadnej z dwóch omawianych tutaj kwestii. Na przykład (1) .toString (36) .sstrstring (7) tworzy pusty ciąg.
amichair

Użycie Math.random().toString(36).substring(2,7)daje oczekiwany wynik, który bardziej przypomina.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

Jest to świetne, ale gdy jest wykonywane w Firefoksie z N = 16, ostatnie ~ 6 cyfr kończy się na zero ... (Ale to zaspokaja pragnienie OP dla 5 losowych znaków).
Edward Newell

126

Najbardziej kompaktowe rozwiązanie, ponieważ slicejest krótsze niż substring. Odejmowanie od końca łańcucha pozwala uniknąć symbolu zmiennoprzecinkowego generowanego przez randomfunkcję:

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

lub nawet

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

Aktualizacja: Dodano jeszcze jedno podejście przy użyciu btoametody:

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);- Co jeśli Math.random()powróci 0.0?
prześwietlenie

@ x-ray, dostaniesz "0";)
Valentin Podkamennyi

2
Dokładnie. ;) A jeśli Math.random()zwraca 0.5wynik jest "0.i". Nie jestem pewien, czy istnieją inne przypadki krawędzi. Chciałem tylko zaznaczyć, że nie jest to poprawna odpowiedź na pytanie (5 znaków z [a-zA-Z0-9]).
prześwietlenie

2
@ rentgen, nie powiem, że to właściwa odpowiedź, mówię tylko, że jest to zwarta wersja powyższej odpowiedzi @doubletap. Osobiście używam, (+new Date + Math.random())aby zapobiec tej sprawie. W każdym razie dzięki za notatkę.
Valentin Podkamennyi

1
To. Nie wiem, dlaczego inne odpowiedzi wymagają tak dużo kodu
John Kejik

100

Coś takiego powinno działać

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

Dzwoń z domyślnym zestawem znaków [a-zA-Z0-9] lub wysyłaj własny:

var randomValue = randomString(5);

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

Wariant przykładu tutaj można znaleźć tutaj: mediacollege.com/internet/javascript/number/random.html
David

1
równie dobrze może po prostu zmniejszyć lenbezpośrednio w whilepętli
drzaus

Dzięki, właśnie opublikowałem poniżej odmianę coffeescript dla tego przykładu: stackoverflow.com/a/26682781/262379
Dinis Cruz

Jeśli będą one używane publicznie, prawdopodobnie powinieneś usunąć samogłoski. Trochę mniej entropii, ale o wiele bezpieczniej, ponieważ nie możesz wygenerować żadnych słów, które mogłyby obrażać ludzi. Dlatego mi się to podoba, ponieważ mogę wysłać własny ciąg znaków. Dobra robota.
Nate Bunney,

Dość hardcore, pracował dla mnie, dzięki!
Zaki Mohammed,

73

Nowsza wersja z operatorem rozprzestrzeniania es6 :

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

  • Jest 30to dowolna liczba, możesz wybrać dowolną długość tokena
  • Jest 36to maksymalna liczba podstawowa, jaką możesz przekazać do numeric.toString () , co oznacza wszystkie cyfry i małe litery az
  • 2Służy do piłki 3th indeks z losowy ciąg, który wygląda tak: "0.mfbiohx64i", możemy podjąć wszelkie indeksu po0.

Czy możesz wytłumaczyć? Zwłaszcza dlaczego przekazujesz 36 do toString () i dlaczego wybierasz trzeci element?
vuza,

5
to najlepsze rozwiązanie
zwycięzca

fajnie, ale to rozwiązanie nie zawiera znaków [AZ] jako pytania, tylko [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));


Najbardziej to lubię. Możesz łatwo zmodyfikować, aby akceptować dodatkowe parametry i zwracać tylko liczby, obniżenia lub ograniczenia. Nie wydaje mi się, żeby ten ultra-skompresowany styl był koniecznywhile(s.length< L) s+= randomchar();
mastaBlasta

3
Również while(L--)to zrobi
vsync

1
Lepiej używać bardziej wytrzymałej 'A'.charCodeAt(0)niż magicznej liczby 55(i podobnie w przypadku 61). Zwłaszcza, że ​​i tak na mojej platformie magiczna liczba, która powraca, to 65. Ten kod również będzie lepiej dokumentował się sam.
Grumdrig,

Stworzyłem tutaj zoptymalizowany pod kątem minimalizacji (46 bajtów) wariant twojej implementacji: stackoverflow.com/a/52412162
Waruyama,

Powodzenia w debugowaniu tego @Waruyama. Do tego właśnie służy webpack!
Dylan Watson,

61

Generator losowych ciągów znaków (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"


Podczas gdy powyższe wykorzystuje dodatkowe kontrole pożądanego wyjścia A / N, A, N , podzielmy je na najważniejsze (tylko alfanumeryczne) dla lepszego zrozumienia:

  • Utwórz funkcję, która akceptuje argument (pożądana długość losowego wyniku ciągu)
  • Utwórz pusty ciąg znaków, var str = "";aby połączyć losowe znaki
  • Wewnątrz pętli utwórz randnumer indeksu od 0 do 61 (0..9 + A..Z + a..z = 62)
  • Utwórz logikę warunkową, aby dostosować / naprawićrand (ponieważ wynosi 0..61), zwiększając ją o pewną liczbę (patrz przykłady poniżej), aby odzyskać właściwą CharCodeliczbę i powiązany znak.
  • Wewnątrz pętli połącz się strzString.fromCharCode( incremented rand )

Wyobraźmy sobie zakresy tabeli znaków 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 )daje zakres od 0..61(czego potrzebujemy).
Naprawmy losowy, aby uzyskać prawidłowe zakresy 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     |

Warunkowa operacja logiczna z powyższej tabeli:

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

Z powyższego wyjaśnienia oto wynikowy fragment alfanumeryczny :

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"

Lub jeśli:

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

Najprostszym sposobem jest:

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

Generuje losowe ciągi 5 znaków na podstawie aktualnego czasu. Przykładowy wynik to 4mtxjlub 4mv90lub4mwp1

Problem polega na tym, że jeśli wywołasz go dwa razy w tej samej sekundzie, wygeneruje ten sam ciąg.

Bezpieczniejszy sposób to:

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

To wygeneruje losowy ciąg 4 lub 5 znaków, zawsze inny. Przykładowy wynik to: 30jzmlub 1r591lub4su1a

W obu przypadkach pierwsza część generuje liczbę losową. Część .toString(36)rzutuje liczbę na podstawową 36 (alfadecymalną) reprezentację.


Nie jestem do końca pewien, jak to odpowiada na pytanie; To 7-letnie pytanie z wieloma prawidłowymi odpowiedziami. Jeśli zdecydujesz się podać nową odpowiedź, powinieneś naprawdę bardzo uważać, aby upewnić się, że twoja odpowiedź jest dobrze wyjaśniona i udokumentowana.
Claies

1
Jeśli używasz Daty, dlaczego po prostu nie użyjesz jej w następujący sposób:(+new Date).toString(36)
starszy kaznodzieja

Podoba mi się twoje rozwiązanie liczb losowych, ale 9e6 daje tylko 9 milionów możliwości w porównaniu z 60,4 milionami dla 5 cyfr (36 ^ 5), więc możesz je zastąpić, (0|Math.random()*6.04e7).toString(36)aby je zakryć.
Le Droid,

1
Chciałem długo losowy ciąg znaków z możliwie krótką procedurą (jak na wersję demonstracyjną kodu), która nie musi być kryptograficznie niesamowita, po prostu produkuj ładny, przypadkowy „puch”. Najbardziej podoba mi się ta odpowiedź (Twoja druga), więc dziękuję. Moje dwa centy: Mogę bić go za spłycenie jednym naciśnięciem klawisza mniej, a to zazwyczaj produkują 13 losowo wybranych znaków (bez okresu) (Math.random()*1e20).toString(36).
Andrew Willems,

jedną z wątpliwości, jakie mam z tą odpowiedzią, jest to, że nie użyje ona [AZ], co zdarza się w pierwotnym pytaniu.
user.friendly

22

Oto kilka prostych wkładek. Zmień, new Array(5)aby ustawić długość.

Włącznie z 0-9a-z

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

Włącznie z 0-9a-zA-Z

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

20

Wiem, że wszyscy już to zrobili, ale miałem ochotę spróbować tego w jak najlżejszy sposób (światło na kod, a nie procesor):

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

console.log(rand(5));

Zajmuje trochę czasu, ale myślę, że to naprawdę pokazuje, jak niesamowita jest składnia javascript.


20
Jeśli próbujesz skrócić kod, current = current ? current : '';po co pisać, kiedy możesz pisać current = current || '';
CaffGeek

9
skoro mówimy tutaj o mikrooptymalizacji, właściwie sugerowałbym pominięcie przypisania zmiennej całkowicie, jeśli nie jest to konieczne:current || (current = '');
Thomas Heymann,

Próba mikrooptymalizacji przy użyciu „ładnego”, ale rekurencyjnego algorytmu marnowania zasobów nie ma sensu :-) Pętla for jest nadal najlepsza w Javascripcie i pokonuje rekurencję przez długi czas, dopóki nie zostaną zrobione naprawdę duże postępy w kodzie optymalizacji środowiska wykonawczego.
Mörre

17

Jeśli używasz Lodash lub Underscore , to takie proste:

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

6
Zastosowania Lodash_.sampleSize('asdfgh',5).join('')
marlo

2
To właściwie nie jest dobre rozwiązanie, ponieważ na dokumentach każda postać pochodzi z unikalnego indeksu. Oznacza to, że nie jest tak naprawdę losowy, ponieważ żadna postać nie może / nigdy się nie powtórzy.
random_user_name

16

Aby spełnić wymaganie [a-zA-Z0-9] i długość = 5, użyj

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

Pojawią się małe litery, wielkie litery i cyfry.


1
Wydaje mi się, że Math.random () może prowadzić do ciągu base64 ze zbyt małą liczbą znaków.
Leif,

14

Jeśli ktoś jest zainteresowany liniowcem (choć nie jest sformatowany jako taki dla Twojej wygody), który przydziela pamięć od razu (ale pamiętaj, że w przypadku małych łańcuchów to naprawdę nie ma znaczenia), oto jak to zrobić:

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

Możesz zastąpić żądaną 5długością łańcucha. Dzięki @AriyaHidayat w tym poście za rozwiązanie mapfunkcji nie działającej na rzadkiej tablicy utworzonej przez Array(5).


13
Każdy program javascript jest „liniowy”, jeśli sformatujesz go jako taki
hacklikecrack

13

Oto metoda, którą stworzyłem.
Utworzy ciąg zawierający zarówno wielkie, jak i małe litery.
Dodatkowo zawarłem funkcję, która utworzy również ciąg alfanumeryczny.

Przykłady robocze:
http://jsfiddle.net/greatbigmassive/vhsxs/ (tylko w wersji alfa)
http://jsfiddle.net/greatbigmassive/PJwg8/ (alfanumeryczny)

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

Aktualizacja lipca 2015 r.
To samo robi, ale ma większy sens i obejmuje wszystkie litery.

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

Dzięki tej funkcji nigdy nie można uzyskać dużej litery większej niż „M” lub małej litery mniejszej niż „n”.
erkanyildiz

Naprawdę? ooch! prawdopodobnie przetestuje to bardziej niż. Hmm, jednak biorąc pod uwagę, że jest to ciąg losowy i nie obchodzi nas, jakie litery są w nim (o ile są losowe), to nadal robi to, co chcemy, co jest ważne, ale tak, zapewni upgrade, dzięki.
Adam

12

Zakładając, że używasz podkreślników, możesz elegancko wygenerować losowy ciąg w dwóch liniach:

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

6
Dzięki temu zwracana wartość będzie miała wszystkie unikalne znaki. Ponadto długość łańcucha jest ograniczona do możliwej długości var.
Jefu

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

Proste, czyste rozwiązanie
Mark Swardstrom

To zasługuje na większą +1
Walid Ammar

10

Szybki i ulepszony algorytm. Nie gwarantuje jednolitości (patrz komentarze).

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
Świetna odpowiedź, ale prawdopodobieństwo nie jest jednolite. Istnieje 62 możliwych znaków i crypto.getRandomValueszwraca jedną z 256 unikalnych wartości. Ponieważ 256 nie jest dzielone przez 62, w rezultacie masz nieco większe prawdopodobieństwo otrzymania znaków AH. Myślę, że najlepszym rozwiązaniem jest zrobienie tego, co zrobił YouTube, i dodanie 2 dodatkowych znaków (ewentualnie -i _) do zestawu znaków. W każdym razie świetna robota - ta odpowiedź wymaga o wiele więcej miłości :)
TeWu

dodanie - i _ to świetny pomysł, ponieważ dostaniesz kompletny zestaw base64 bezpieczny dla
adresu

8

Problem z odpowiedziami na pytania „Potrzebuję losowych ciągów” (w dowolnym języku) polega na tym, że praktycznie każde rozwiązanie wykorzystuje wadliwą podstawową specyfikację długości łańcucha . Same pytania rzadko ujawniają, dlaczego potrzebne są losowe ciągi, ale rzuciłbym wyzwanie, że rzadko potrzebujesz losowych ciągów, powiedzmy 8. To, czego zawsze potrzebujesz, to pewna liczba unikatowych ciągów , na przykład do wykorzystania jako identyfikatory w jakimś celu.

Istnieją dwa wiodące sposoby uzyskania ściśle unikatowych ciągów: deterministycznie (co nie jest losowe) i przechowywanie / porównywanie (co jest uciążliwe). Co robimy? Porzucamy ducha. Idziemy z probabilistycznego wyjątkowości zamiast. To znaczy, akceptujemy, że istnieje pewne (choć niewielkie) ryzyko, że nasze łańcuchy nie będą unikalne. W tym przypadku pomocne jest zrozumienie prawdopodobieństwa zderzenia i entropii .

Dlatego zmienię niezmienną potrzebę jako wymagającą pewnej liczby ciągów z niewielkim ryzykiem powtórzenia. Jako konkretny przykład, powiedzmy, że chcesz wygenerować potencjał 5 milionów identyfikatorów. Nie chcesz przechowywać i porównywać każdego nowego łańcucha i chcesz, aby były losowe, więc akceptujesz ryzyko powtórzenia. Jako przykład, powiedzmy, że ryzyko jest mniejsze niż 1 przy trylionach szansy na powtórzenie. Jakiej długości sznurka potrzebujesz? To pytanie jest nieokreślone, ponieważ zależy od użytych znaków. Ale co ważniejsze, jest to mylące. Potrzebujesz specyfikacji entropii łańcuchów, a nie ich długości. Entropia może być bezpośrednio związana z prawdopodobieństwem powtórzenia w pewnej liczbie ciągów. Długość łańcucha nie może.

I tu może pomóc biblioteka taka jak EntropyString . Aby wygenerować losowe identyfikatory, które mają mniej niż 1, z bilionem szansy na powtórzenie w 5 milionach ciągów przy użyciu 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-stringużywa domyślnie zestawu znaków zawierającego 32 znaki. Istnieją inne predefiniowane zestawy znaków, a także możesz określić własne znaki. Na przykład generowanie identyfikatorów z taką samą entropią jak powyżej, ale przy użyciu znaków szesnastkowych:

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

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

const string = random.string(bits)

„27b33372ade513715481f”

Zwróć uwagę na różnicę długości łańcucha wynikającą z różnicy w całkowitej liczbie znaków w użytym zestawie znaków. Ryzyko powtórzenia w określonej liczbie potencjalnych ciągów jest takie samo. Długości łańcucha nie są. A co najważniejsze, ryzyko powtórzenia i potencjalna liczba ciągów jest wyraźna. Nigdy więcej zgadywania przy długości łańcucha.


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

To jest tak czyste, jak to możliwe. Jest również szybki, http://jsperf.com/ay-random-string .


Dla mnie to zawsze generuje losowe ciągi znaków z strLength - 1: - /
xanderiel,

3
Przejście z --strLengthna strLength--to naprawia dla mnie.
xanderiel,

7

Możesz przeglądać tablicę elementów i rekurencyjnie dodawać je do zmiennej łańcuchowej, na przykład jeśli chcesz losową sekwencję DNA:

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

Nie znalazłem czystego rozwiązania do obsługi zarówno małych, jak i wielkich liter.

Obsługa tylko małych liter:

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

Opierając się na tym rozwiązaniu do obsługi małych i wielkich liter:

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

Zmień 5w, substr(2, 5)aby dopasować do potrzebnej długości.


6

Jedna wkładka:

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

Aby było krótsze, zmień argument Array(15)na mniejszą wartość. Np Array(4). :
Andrew

Naprawdę uwielbiam to rozwiązanie, proste i jasne. Generuje 15 liczb losowych od 0 do 1, generuje wartość szesnastkową, a następnie usuwa pierwsze dwa znaki. Wreszcie łączy je wszystkie razem.
Siscia

5

To na pewno działa

<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

A może coś takiego: Date.now().toString(36) niezbyt losowe, ale krótkie i dość wyjątkowe za każdym razem, gdy to nazwiesz.


1
Niestety nie będzie to wyjątkowe, ponieważ Date.now()ma rozdzielczość tylko milisekundową. Na przykład w prostej pętli otrzymasz wiele duplikatów. for (let i = 0; i < 10; ++i) { console.log(Date.now().toString(36)); }.
Nate

5

Znaki alfanumeryczne bez rozróżniania wielkości liter:

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

Zaletą tej funkcji jest to, że można uzyskać losowy ciąg różnej długości i zapewnia on długość łańcucha.

Rozróżnianie wielkości liter Wszystkie znaki:

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

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

Niestandardowe znaki

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


Ta odpowiedź bardziej pasuje do mojego przypadku użycia. Byłoby fajnie, gdybyś mógł dodać znak var possiblepodobny do akceptowanej odpowiedzi, więc wynik funkcji jest bardziej konfigurowalny.
Denis.Sabolotni

4

Wygeneruj ciąg znaków o długości 10 znaków. Długość jest ustawiana przez parametr (domyślnie 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

Możesz użyć coderain . Jest to biblioteka do generowania losowych kodów według podanego wzorca. Użyj #jako symbolu zastępczego dla wielkich i małych liter oraz cyfr:

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

Istnieją inne symbole zastępcze, takie jak Awielkie litery lub9 cyfry.

Przydatne może być to wywołanie .next() zawsze daje unikalny wynik, więc nie musisz się martwić o duplikaty.

Oto aplikacja demonstracyjna, która generuje listę unikalnych losowych kodów .

Pełne ujawnienie: jestem autorem coderain.


NIE NIE NIE - używaj metod natywnych.
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.