セットからランダムに選択した文字で構成される5文字の文字列が必要です[a-zA-Z0-9]
。
JavaScriptでこれを行う最良の方法は何ですか?
Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 5);
セットからランダムに選択した文字で構成される5文字の文字列が必要です[a-zA-Z0-9]
。
JavaScriptでこれを行う最良の方法は何ですか?
Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 5);
回答:
これはうまくいくと思います:
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));
+=
このような文字列で使用するとO(n ^ 2)の動作が発生することに注意してください。より長い文字列を作成する場合は、個々の文字の配列を作成し、最後にそれらを結合する必要があります。
+=
は、ループ内で使用されている場合でも、何らかの理由で高速であることがよくあります-jsperf.com/join-vs-concatenation
let r = Math.random().toString(36).substring(7);
console.log("random", r);
注:上記のアルゴリズムには次の弱点があります。
Math.random()
実装によっては、予測可能な(「ランダムに見える」が、実際にはランダムではない)出力を生成する場合があります。結果の文字列は、一意性または予測不能性を保証する必要がある場合には適していません。Math.random().toString(36).substr(2, 5)
、.substring(7)
5文字より長くなるため。まだまだ満点!
toString
JavaScriptの数値タイプのメソッドは、オプションのパラメーターを使用して、数値を指定された基数に変換します。たとえば、2つ渡すと、2進数で表された数値が表示されます。hex(base 16)と同様に、base 36は9を超える数字を表すために文字を使用します。乱数をbase 36に変換することにより、一見ランダムに見える文字と数字の束ができあがります。
(Math.random() + 1).toString(36).substring(7);
オプション1
このサーバー側で実行できる場合は、cryptoモジュールを使用してください-
var crypto = require("crypto");
var id = crypto.randomBytes(20).toString('hex');
// "bb5dc8842ca31d4603d6aa11448d1654"
結果の文字列は、生成したランダムバイトの2倍の長さになります。16進数にエンコードされた各バイトは2文字です。20バイトは40桁の16進数です。
オプション2
このクライアント側で行う必要がある場合は、uuidモジュールを試してください。
var uuid = require("uuid");
var id = uuid.v4();
// "110ec58a-a0f2-4ac4-8393-c866d813b8d1"
オプション3
このクライアントを-サイドで実行する必要があり、古いブラウザをサポートする必要がない場合は、依存関係なしで実行できます-
// 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"
詳細についてはcrypto.getRandomValues
-
この
crypto.getRandomValues()
方法では、暗号的に強力なランダム値を取得できます。パラメータとして指定された配列には、乱数(暗号の意味ではランダム)が入ります。
ここに小さなコンソールの例があります-
> 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のサポートについては、使用できます-
(window.crypto || window.msCrypto).getRandomValues(arr)
ブラウザのカバレッジについては、https://caniuse.com/#feat=getrandomvaluesを参照してください
.map()
オプション3では不要です。Array.from(arr, dec2hex).join('')
=== Array.from(arr).map(dec2hex).join('')
。これらの機能を紹介してくれてありがとう:-)
require
モジュールはサーバー側でしか使用できませんか?
ここで見つかった上位の回答の一部とは対照的に、正確に5つのランダムな文字を返します。
Math.random().toString(36).substr(2, 5);
Math.random().toString(36)
5文字未満の数値を返す場合はどうなりますか?
function getRandomString() { var result = ''; while (!result) result = Math.random().toString(36).substring(2); return result; };
doubletapの優れた答えの改善点を以下に示します。オリジナルには、2つの欠点があります。
まず、他の人が述べたように、短い文字列または空の文字列(乱数が0の場合)さえ生成する可能性はわずかであり、アプリケーションを破壊する可能性があります。これが解決策です:
(Math.random().toString(36)+'00000000000000000').slice(2, N+2)
次に、元のソリューションと上記のソリューションの両方で、文字列サイズNが16文字に制限されています。次のコードは、任意のNに対してサイズNの文字列を返します(ただし、N> 16を使用しても、ランダム性が増加したり、衝突の確率が低下したりすることはありません)。
Array(N+1).join((Math.random().toString(36)+'00000000000000000').slice(2, 18)).slice(0, N)
説明:
さらなる考え:
更新:
ここに私が思いついた他のいくつかの機能的なスタイルのワンライナーがあります。上記のソリューションとは次の点が異なります。
だから、あなたの選んだアルファベットは
var s = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
次に、これら2つは互いに同等であるため、直感的な方を選択できます。
Array(N).join().split(',').map(function() { return s.charAt(Math.floor(Math.random() * s.length)); }).join('');
そして
Array.apply(null, Array(N)).map(function() { return s.charAt(Math.floor(Math.random() * s.length)); }).join('');
編集:
私はのように思えるqubyteとマルタイン・デ・Millianoは後者に同様のソリューションを思いついた(栄光!)、私は何とか逃しました。彼らは一見すると短く見えないので、誰かが本当にワンライナーを望んでいる場合に備えて、とにかくここに置いておきます:-)
また、すべてのソリューションで「新しい配列」を「配列」に置き換えて、さらに数バイトを削りました。
(Math.random()+1).toString(36).substring(7);
Math.random().toString(36).substring(2,7)
すると、より類似した期待される結果が得られます.substring(2, n+2)
Array.apply(null, {length: 5}).map(function() { return s.charAt(Math.floor(Math.random() * s.length)); }).join('')
slice
より短いので、最もコンパクトなソリューションsubstring
。文字列の末尾から減算すると、random
関数によって生成される浮動小数点シンボルを回避できます。
Math.random().toString(36).slice(-5);
あるいは
(+new Date).toString(36).slice(-5);
更新:btoa
メソッドを使用してもう1つのアプローチを追加しました:
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);
- Math.random()
戻ってきたらどうなる0.0
?
"0"
;)
Math.random()
返さ0.5
れる場合は"0.i"
です。他のエッジケースがあるかどうかは不明です。これは質問に対する正しい答えではないことを指摘したかっただけです([a-zA-Z0-9]の5文字)。
(+new Date + Math.random())
このケースを防ぐために個人的に使用しています。とにかく、メモをありがとう。
このようなものがうまくいくはずです
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;
}
デフォルトの文字セット[a-zA-Z0-9]で呼び出すか、独自に送信します。
var randomValue = randomString(5);
var randomValue = randomString(5, 'PICKCHARSFROMTHISSET');
len
直接デクリメントすることもできwhile
ます
es6 スプレッド演算子を含む新しいバージョン:
[...Array(30)].map(() => Math.random().toString(36)[2]).join('')
30
任意の数である、あなたが望む任意のトークンの長さを選ぶことができます36
は、numeric.toString()に渡すことができる最大の基数です。これは、すべての数字とzの小文字を意味します2
このようになりますランダムな文字列から第3回のインデックスを選択するために使用されます"0.mfbiohx64i"
、我々は後に任意のインデックスを取ることができます0.
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));
while(s.length< L) s+= randomchar();
while(L--)
を実行します
'A'.charCodeAt(0)
マジックナンバーよりもロバスト性を使用することをお勧めします55
(同様に61
)。特に、私のプラットフォームではとにかく、返されるマジックナンバーはです65
。そのコードは自己文書化にも優れています。
/**
* 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"
上記では、目的のA / N、A、N出力に対して追加のチェックを使用していますが、理解を深めるために、本質的な要素(英数字のみ)に分解してみましょう。
var str = "";
ランダムな文字を連結するような空の文字列を作成しますrand
ます(0..9 + A..Z + a..z = 62)rand
CharCode
str
ますString.fromCharCode( incremented rand )
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 )
0..61
(必要なもの)の範囲を指定します。
ランダムを修正して、正しい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 |
上記の表の条件付き演算ロジック:
rand += rand>9 ? ( rand<36 ? 55 : 61 ) : 48 ;
// rand += true ? ( true ? 55 else 61 ) else 48 ;
上記の説明から、これが結果の英数字のスニペットです:
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"
または、次の場合:
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))
最も簡単な方法は次のとおりです。
(new Date%9e6).toString(36)
これにより、現在の時刻に基づいて5文字のランダムな文字列が生成されます。出力例は4mtxj
or 4mv90
または4mwp1
この問題は、同じ秒に2回呼び出すと、同じ文字列が生成されることです。
より安全な方法は次のとおりです。
(0|Math.random()*9e6).toString(36)
これにより、常に異なる4文字または5文字のランダムな文字列が生成されます。出力例は30jzm
or 1r591
またはor4su1a
どちらの方法でも、最初の部分は乱数を生成します。.toString(36)
一部はそれをbase36(alphadecimal)表現に番号をキャスト。
(+new Date).toString(36)
(0|Math.random()*6.04e7).toString(36)
。
(Math.random()*1e20).toString(36)
。
ここに簡単なワンライナーがあります。変更new Array(5)
して長さを設定します。
0-9a-z
new Array(5).join().replace(/(.|$)/g, function(){return ((Math.random()*36)|0).toString(36);})
0-9a-zA-Z
new Array(5).join().replace(/(.|$)/g, function(){return ((Math.random()*36)|0).toString(36)[Math.random()<.5?"toString":"toUpperCase"]();});
私は誰もがすでにそれを正しく理解していることを知っていますが、私はこれを可能な限り最も軽量な方法(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));
頭を一周するには少し時間がかかりますが、JavaScriptの構文の素晴らしさを実際に示していると思います。
current = current ? current : '';
ことができるのに、なぜ書くのかcurrent = current || ''
。
current || (current = '');
LodashまたはUnderscoreを使用している場合、それはとても簡単です:
var randomVal = _.sample('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', 5).join('');
_.sampleSize('asdfgh',5).join('')
一度にメモリを割り当てるワンライナー(便宜上、そのようにフォーマットされていませんが)に興味がある場合(ただし、小さな文字列の場合は重要ではないことに注意してください)、その方法を次に示します。
Array.apply(0, Array(5)).map(function() {
return (function(charset){
return charset.charAt(Math.floor(Math.random() * charset.length))
}('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'));
}).join('')
5
必要な文字列の長さに置き換えることができます。中@AriyaHidayatのおかげで、この記事へのソリューションのmap
機能により作成スパースアレイ上で動作していませんArray(5)
。
これが私が作成したメソッドです。
大文字と小文字の両方を含む文字列を作成します。
さらに、英数字の文字列を作成する関数も含めました。
作業例:
http : //jsfiddle.net/greatbigmassive/vhsxs/ (アルファ版のみ)
http://jsfiddle.net/greatbigmassive/PJwg8/(アルファ版)
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;
}
2015年7月のアップグレード
これは同じことを行いますが、より意味があり、すべての文字が含まれます。
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)));
}
underscorejsを使用していると仮定すると、ランダムな文字列を2行だけでエレガントに生成できます。
var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
var random = _.sample(possible, 5).join('');
const c = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
const s = [...Array(5)].map(_ => c[~~(Math.random()*c.length)]).join('')
高速で改善されたアルゴリズム。ユニフォームを保証しません(コメントを参照)。
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;
}
crypto.getRandomValues
、256の一意の値の1つを返します。256は62で除算されないため、文字AHを取得する確率がわずかに高くなります。最善の解決策は、YouTubeが行ったことを実行し、2つの文字(-
と_
)を文字セットに追加することです。とにかく素晴らしい仕事-この回答にはもっと多くの愛が必要です:)
「ランダムな文字列が必要です」という質問(どんな言語でも)に対する応答の問題は、事実上すべてのソリューションが文字列長の欠陥のある主要な仕様を使用していることです。質問自体は、ランダム文字列が必要な理由を明らかにすることはめったにありませんが、長さのランダム文字列が必要になることはめったにありません。たとえば、8です。常に必要なのは、いくつかの一意の文字列です。たとえば、何らかの目的で識別子として使用するために、。
厳密に一意の文字列を取得するには、主に2つの方法があります。確定的(ランダムではない)と保存/比較(煩わしい)です。私たちは何をしますか?私たちは幽霊をあきらめます。代わりに、確率的一意性を使用します。つまり、文字列が一意でなくなるリスクが(わずかではありますが)あることを受け入れます。これは、衝突確率とエントロピーを理解することが役立つ場所です。
したがって、繰り返しのリスクが少ないいくつかの文字列を必要とするので、不変のニーズを言い換えます。具体的な例として、500万のIDを生成したいとします。新しい文字列を保存して比較するのではなく、文字列をランダムにしたいので、繰り返しのリスクを受け入れます。例として、1兆回の繰り返しで1未満のリスクがあるとします。では、どのくらいの長さのストリングが必要ですか?まあ、それは使用される文字に依存するので、その質問は十分に指定されていません。しかし、より重要なのは、それが誤った見方です。必要なのは、文字列の長さではなく、文字列のエントロピーの仕様です。エントロピーは、いくつかの文字列で繰り返しが発生する確率に直接関係しています。文字列の長さはできません。
そして、これがEntropyStringのようなライブラリが役立つところです。を使用して、500万の文字列で1兆回の繰り返しの可能性が1未満のランダムIDを生成するには、次のようにします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-string
デフォルトでは32文字の文字セットを使用します。他にも定義済みの文字セットがあり、独自の文字を指定することもできます。たとえば、上記と同じエントロピーで16進数文字を使用してIDを生成します。
import {Random, Entropy, charSet16} from './entropy-string'
const random = new Random(charSet16)
const bits = Entropy.bits(5e6, 1e12)
const string = random.string(bits)
「27b33372ade513715481f」
使用する文字セットの合計文字数の違いによる文字列の長さの違いに注意してください。指定された数の潜在的な文字列で繰り返されるリスクは同じです。文字列の長さは異なります。そして何よりも、繰り返しのリスクと文字列の潜在的な数は明白です。文字列の長さを推測する必要はもうありません。
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('');
}
これは可能な限りクリーンです。http://jsperf.com/ay-random-stringも高速です。
strLength - 1
:-/
--strLength
に切り替えるとstrLength--
修正されます。
一発ギャグ:
Array(15).fill(null).map(() => Math.random().toString(36).substr(2)).join('')
// Outputs: 0h61cbpw96y83qtnunwme5lxk1i70a6o5r5lckfcyh1dl9fffydcfxddd69ada9tu9jvqdx864xj1ul3wtfztmh2oz2vs3mv6ej0fe58ho1cftkjcuyl2lfkmxlwua83ibotxqc4guyuvrvtf60naob26t6swzpil
Array(15)
より小さい値に変更します。例:Array(4)
。
これは確かに機能します
<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>
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));
この関数の利点は、さまざまな長さのランダム文字列を取得でき、文字列の長さが保証されることです。
function randStr(len) {
let s = '';
while (len--) s += String.fromCodePoint(Math.floor(Math.random() * (126 - 33) + 33));
return s;
}
// usage
console.log(randStr(50));
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
var possible
受け入れられた回答に「いいね!」を追加できると便利です。そのため、関数の結果はより設定可能です。
10文字の文字列を生成します。長さはパラメータで設定されます(デフォルトは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;
}
coderainを使用できます。与えられたパターンに従ってランダムなコードを生成するライブラリです。#
大文字、小文字、数字のプレースホルダーとして使用します。
var cr = new CodeRain("#####");
console.log(cr.next());
A
大文字や9
数字のような他のプレースホルダーがあります。
便利なのは、呼び出し.next()
によって常に固有の結果が得られるため、重複を心配する必要がないことです。
これは、一意のランダムコードのリストを生成するデモアプリケーションです。
完全な開示:私はコードレインの作者です。
true-random
結果がありません!彼らだけpseudo-random
です。保護またはセキュリティのためにランダムな文字列を使用するときは、それらを使用しないでください!!! これらのAPIのいずれかを試してください:random.org