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?
javascript
random
Tom Lehman
źródło
źródło
true-random
rezultatu! Oni są tylkopseudo-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.orgMath.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 5);
Odpowiedzi:
Myślę, że to zadziała dla ciebie:
źródło
+=
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.+=
jest często z jakiegoś powodu szybszy, nawet używany wewnątrz pętli - jsperf.com/join-vs-concatenationcrypto
zamiast tego.Uwaga: powyższy algorytm ma następujące słabości:
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ść.źródło
Math.random().toString(36).substr(2, 5)
, ponieważ.substring(7)
powoduje, że ma on więcej niż 5 znaków. Nadal pełne punkty!toString
Metoda 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.(Math.random() + 1).toString(36).substring(7);
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 -
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 -
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 -
Aby uzyskać więcej informacji na temat
crypto.getRandomValues
-Oto mały przykład konsoli -
Do obsługi IE11 możesz użyć -
Aby zapoznać się z zasięgiem przeglądarki, patrz https://caniuse.com/#feat=getrandomvalues
źródło
.map()
w opcji 3.Array.from(arr, dec2hex).join('')
===Array.from(arr).map(dec2hex).join('')
. Dziękujemy zarequire
moduł nie może być używany tylko po stronie serwera?Krótko, łatwo i niezawodnie
Zwraca dokładnie 5 losowych znaków, w przeciwieństwie do niektórych najwyżej ocenianych odpowiedzi tutaj.
źródło
Math.random().toString(36)
zwróci liczbę składającą się z mniej niż 5 znaków?function getRandomString() { var result = ''; while (!result) result = Math.random().toString(36).substring(2); return result; };
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:
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):
Wyjaśnienie:
Dalsze przemyślenia:
Aktualizacja:
Oto kilka innych funkcjonalnych stylów, które wymyśliłem. Różnią się od powyższego rozwiązania tym, że:
Powiedzmy, że twoim alfabetem jest
Te dwa są sobie równe, więc możesz wybrać, który z nich jest bardziej intuicyjny:
i
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.
źródło
(Math.random()+1).toString(36).substring(7);
Math.random().toString(36).substring(2,7)
daje oczekiwany wynik, który bardziej przypomina.substring(2, n+2)
Array.apply(null, {length: 5}).map(function() { return s.charAt(Math.floor(Math.random() * s.length)); }).join('')
Najbardziej kompaktowe rozwiązanie, ponieważ
slice
jest krótsze niżsubstring
. Odejmowanie od końca łańcucha pozwala uniknąć symbolu zmiennoprzecinkowego generowanego przezrandom
funkcję:lub nawet
Aktualizacja: Dodano jeszcze jedno podejście przy użyciu
btoa
metody:źródło
Math.random().toString(36).slice(-5);
- Co jeśliMath.random()
powróci0.0
?"0"
;)Math.random()
zwraca0.5
wynik 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]).(+new Date + Math.random())
aby zapobiec tej sprawie. W każdym razie dzięki za notatkę.Coś takiego powinno działać
Dzwoń z domyślnym zestawem znaków [a-zA-Z0-9] lub wysyłaj własny:
źródło
len
bezpośrednio wwhile
pętliNowsza wersja z operatorem rozprzestrzeniania es6 :
[...Array(30)].map(() => Math.random().toString(36)[2]).join('')
30
to dowolna liczba, możesz wybrać dowolną długość tokena36
to maksymalna liczba podstawowa, jaką możesz przekazać do numeric.toString () , co oznacza wszystkie cyfry i małe litery az2
Służy do piłki 3th indeks z losowy ciąg, który wygląda tak:"0.mfbiohx64i"
, możemy podjąć wszelkie indeksu po0.
źródło
źródło
while(s.length< L) s+= randomchar();
while(L--)
to zrobi'A'.charCodeAt(0)
niż magicznej liczby55
(i podobnie w przypadku61
). Zwłaszcza, że i tak na mojej platformie magiczna liczba, która powraca, to65
. Ten kod również będzie lepiej dokumentował się sam.Generator losowych ciągów znaków (Alpha-Numeric | Alpha | Numeric)
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:
var str = "";
aby połączyć losowe znakirand
numer indeksu od 0 do 61 (0..9 + A..Z + a..z = 62)rand
(ponieważ wynosi 0..61), zwiększając ją o pewną liczbę (patrz przykłady poniżej), aby odzyskać właściwąCharCode
liczbę i powiązany znak.str
zString.fromCharCode( incremented rand )
Wyobraźmy sobie zakresy tabeli znaków ASCII :
Math.floor( Math.random * 62 )
daje zakres od0..61
(czego potrzebujemy).Naprawmy losowy, aby uzyskać prawidłowe zakresy charCode :
Warunkowa operacja logiczna z powyższej tabeli:
Z powyższego wyjaśnienia oto wynikowy fragment alfanumeryczny :
Lub jeśli:
źródło
Najprostszym sposobem jest:
Generuje losowe ciągi 5 znaków na podstawie aktualnego czasu. Przykładowy wynik to
4mtxj
lub4mv90
lub4mwp1
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:
To wygeneruje losowy ciąg 4 lub 5 znaków, zawsze inny. Przykładowy wynik to:
30jzm
lub1r591
lub4su1a
W obu przypadkach pierwsza część generuje liczbę losową. Część
.toString(36)
rzutuje liczbę na podstawową 36 (alfadecymalną) reprezentację.źródło
(+new Date).toString(36)
(0|Math.random()*6.04e7).toString(36)
aby je zakryć.(Math.random()*1e20).toString(36)
.Oto kilka prostych wkładek. Zmień,
new Array(5)
aby ustawić długość.Włącznie z
0-9a-z
Włącznie z
0-9a-zA-Z
źródło
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):
Zajmuje trochę czasu, ale myślę, że to naprawdę pokazuje, jak niesamowita jest składnia javascript.
źródło
current = current ? current : '';
po co pisać, kiedy możesz pisaćcurrent = current || ''
;current || (current = '');
Jeśli używasz Lodash lub Underscore , to takie proste:
źródło
_.sampleSize('asdfgh',5).join('')
Aby spełnić wymaganie [a-zA-Z0-9] i długość = 5, użyj
Pojawią się małe litery, wielkie litery i cyfry.
źródło
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ć:
Możesz zastąpić żądaną
5
długością łańcucha. Dzięki @AriyaHidayat w tym poście za rozwiązaniemap
funkcji nie działającej na rzadkiej tablicy utworzonej przezArray(5)
.źródło
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)
Aktualizacja lipca 2015 r.
To samo robi, ale ma większy sens i obejmuje wszystkie litery.
źródło
Zakładając, że używasz podkreślników, możesz elegancko wygenerować losowy ciąg w dwóch liniach:
źródło
źródło
Szybki i ulepszony algorytm. Nie gwarantuje jednolitości (patrz komentarze).
źródło
crypto.getRandomValues
zwraca 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 :)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
:entropy-string
uż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: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.
źródło
To jest tak czyste, jak to możliwe. Jest również szybki, http://jsperf.com/ay-random-string .
źródło
strLength - 1
: - /--strLength
nastrLength--
to naprawia dla mnie.Możesz przeglądać tablicę elementów i rekurencyjnie dodawać je do zmiennej łańcuchowej, na przykład jeśli chcesz losową sekwencję DNA:
źródło
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ń
5
w,substr(2, 5)
aby dopasować do potrzebnej długości.źródło
Jedna wkładka:
źródło
Array(15)
na mniejszą wartość. NpArray(4)
. :To na pewno działa
źródło
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.źródło
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)); }
.Znaki alfanumeryczne bez rozróżniania wielkości liter:
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:
Niestandardowe znaki
źródło
var possible
podobny do akceptowanej odpowiedzi, więc wynik funkcji jest bardziej konfigurowalny.Wygeneruj ciąg znaków o długości 10 znaków. Długość jest ustawiana przez parametr (domyślnie 10).
źródło
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:Istnieją inne symbole zastępcze, takie jak
A
wielkie 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.
źródło