JavaScriptでランダムな文字列/文字を生成する


1780

セットからランダムに選択した文字で構成される5文字の文字列が必要です[a-zA-Z0-9]

JavaScriptでこれを行う最良の方法は何ですか?


48
警告:答えはどれもtrue-random結果がありません!彼らだけpseudo-randomです。保護またはセキュリティのためにランダムな文字列を使用するときは、それらを使用しないでください!!! これらのAPIのいずれかを試してください:random.org
Ron van der Heijden

48
Math.random()。toString(36).replace(/ [^ az] + / g、 '')
Muaz Khan

13
溶液を溶液に入れてください。
chryss

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

12
注意HTML5 webcrypto randomness APIは実際のランダム性を提供します。
mikemaccana 2016年

回答:


2431

これはうまくいくと思います:

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
これは短い文字列では問題ありませんが、+=このような文字列で使用するとO(n ^ 2)の動作が発生することに注意してください。より長い文字列を作成する場合は、個々の文字の配列を作成し、最後にそれらを結合する必要があります。
dan_waterworth

97
@dan_waterworthそれはおそらくほとんどでは問題ではないいずれかの場合:codinghorror.com/blog/2009/01/...
アレックス・リース

7
@dan_waterworth、実際に+=は、ループ内で使用されている場合でも、何らかの理由で高速であることがよくあります-jsperf.com/join-vs-concatenation
Konrad Borowski

18
@JonathanPaulson 数字を見せてください。jsperfリンクまたはjsperf.com/sad-tragedy-of-microoptimizationまたはsitepen.com/blog/2008/05/09/string-performance-an-analysisなどの前のコメントを参照してください。また、この質問には5つの連結しか含まれていません。
Alex Reece

11
@codenamejames パスワードソルティングではこれを使用しないでください。安全ではなく、疑似ランダムのみです。Nodeを使用している(クライアント側でソルトしている場合、どこから開始すればよいかわからない)と想定して、crypto代わりに使用します。
2015年

2330

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

注:上記のアルゴリズムには次の弱点があります。

  • 浮動小数点を文字列化するときに末尾のゼロが削除されるため、0〜6文字の範囲で生成されます。
  • それは恐ろしく複雑な浮動小数点数を文字列化するために使用されるアルゴリズムに深く依存します。(「浮動小数点数を正確に印刷する方法」というペーパーを参照してください。)
  • Math.random()実装によっては、予測可能な(「ランダムに見える」が、実際にはランダムではない)出力を生成する場合があります。結果の文字列は、一意性または予測不能性を保証する必要がある場合には適していません。
  • 6つの一様にランダムで予測不可能な文字が生成されたとしても、誕生日のパラドックスがあるため、約50,000の文字列のみを生成した後に重複が発生することが予想されます。(sqrt(36 ^ 6)= 46656)

276
Math.random().toString(36).substr(2, 5).substring(7)5文字より長くなるため。まだまだ満点!
ドラゴン

81
@Scoop toStringJavaScriptの数値タイプのメソッドは、オプションのパラメーターを使用して、数値を指定された基数に変換します。たとえば、2つ渡すと、2進数で表された数値が表示されます。hex(base 16)と同様に、base 36は9を超える数字を表すために文字を使用します。乱数をbase 36に変換することにより、一見ランダムに見える文字と数字の束ができあがります。
Chris Baker、

76
美しく見えますが、まれに空の文字列が生成されます。randomが0、0.5、0.25、0.125 ...を返す場合、空または短い文字列になります。
gertas 2013年

67
@gertasこれは回避できます(Math.random() + 1).toString(36).substring(7);
ジョージ・リース

84
男、これは事実上役に立たない。それを1000000回だけ実行すると、通常、約110000回の繰り返し発生が得られます。while(i <1000000){val = Math.random()。toString(36).substring(7); if(values [val]){duplicateCount ++; } values [val] = 1; i ++; } console.log( "TOTAL DUPLICATES"、duplicateCount);
hacklikecrack 2013

463

Math.randomはこの種のものに悪い

オプション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を参照してください


4
丁度。UUIDはモノにIDを割り当てるのに適していますが、ランダムな文字列として使用することは、この(そしておそらく他の)理由から、あまり良い考えではありません。
wmassingham 2015

2
.map()オプション3では不要です。Array.from(arr, dec2hex).join('')=== Array.from(arr).map(dec2hex).join('')。これらの機能を紹介してくれてありがとう:-)
Fred Gandt

6
回答で、オプション2もnode.jsが機能する必要があることを述べてください。これは純粋なJavaScriptではありません。
Esko、

5
より暗号的に安全ですが、0-9とaf(16進数)のみを出力し、0-9、az、AZは出力しないため、これは実際には質問の要件を満たしていません。
qJake 2018年

1
requireモジュールはサーバー側でしか使用できませんか?
aJetHorn

173

短く、簡単で信頼できる

ここで見つかった上位の回答の一部とは対照的に、正確に5つのランダムな文字を返します。

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

9
Math.random().toString(36)5文字未満の数値を返す場合はどうなりますか?
Michael Litvin 2017年

3
まあ、それは@Aperçuからの興味深い告発です。私がソリューションを発明したとは言っていませんが、私のプロジェクトで何年も使っています。そして、あなたが言及したコメントとは何の関係もありません。そして、SOで重要なのは、適切な場所にある最も有用な情報であり、それが他の場所にもすでに存在している場合であっても、確信しています。幸いにも、少なくとも51人がこの回答が役に立ったようです。どういたしまして!
Silver Ringvee 2017年

3
Math.random()が0を返す場合に空の文字列を取得しないようにするために使用できますfunction getRandomString() { var result = ''; while (!result) result = Math.random().toString(36).substring(2); return result; };
mikep

5
@rinogo Math.random()は0を返すことができなく1 developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
mikep

6
私はこのコードを1,000,000,000回実行しましたが、それでも空の文字列を取得しませんでした:jsfiddle.net/mtp5730r空の文字列を取得しても、かなり安全だと思います。
MacroMan、

157

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)

説明:

  1. [0,1)の範囲、つまり0(包括的)から1(排他的)の間の乱数を選択します。
  2. 数値をbase-36文字列に変換します。つまり、0〜9およびa〜zの文字を使用します。
  3. ゼロを埋めます(最初の問題を解決します)。
  4. 先頭の「0」を切り取ります。接頭辞と余分なパディングゼロ。
  5. 少なくともN文字が含まれるように文字列を十分な回数繰り返します(短いランダム文字列を区切り文字として使用して空の文字列を結合します)。
  6. 文字列から正確にN文字をスライスします。

さらなる考え:

  • このソリューションでは大文字を使用しませんが、ほとんどすべての場合(しゃれは意図されていません)、それは重要ではありません。
  • 元の回答のN = 16での最大文字列長は、Chromeで測定されています。FirefoxではN = 11ですが、説明したように、2番目の解決策は、要求された文字列の長さをサポートすることであり、ランダム性を追加することではないため、大きな違いはありません。
  • 返されるすべての文字列は、少なくともMath.random()によって返される結果が均等に分散される限り、等しい確率で返されます(これはいずれにせよ、暗号強度のランダム性ではありません)。
  • サイズNのすべての可能な文字列が返されるとは限りません。2番目のソリューションではこれは明白です(小さい方の文字列が単純に複製されているため)。ただし、元の回答ではこれが当てはまります。base-36への変換では、最後の数ビットが元のランダムビットの一部ではない可能性があるためです。具体的には、Math.random()。toString(36)の結果を見ると、最後の文字が均等に分散されていないことがわかります。繰り返しになりますが、ほとんどすべての場合問題ではありませんが、短い文字列(N = 1など)が影響を受けないように、ランダム文字列の最後ではなく最初から最後の文字列をスライスします。

更新:

ここに私が思いついた他のいくつかの機能的なスタイルのワンライナーがあります。上記のソリューションとは次の点が異なります。

  • それらは明示的な任意のアルファベットを使用します(より一般的で、大文字と小文字の両方を要求する元の質問に適しています)。
  • 長さNのすべての文字列は、返される確率が等しくなります(つまり、文字列は繰り返しを含みません)。
  • これらはtoString(36)トリックではなくマップ関数に基づいているため、より簡単で理解しやすくなっています。

だから、あなたの選んだアルファベットは

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は後者に同様のソリューションを思いついた(栄光!)、私は何とか逃しました。彼らは一見すると短く見えないので、誰かが本当にワンライナーを望んでいる場合に備えて、とにかくここに置いておきます:-)

また、すべてのソリューションで「新しい配列」を「配列」に置き換えて、さらに数バイトを削りました。


なぜ1を足さないのですか?(Math.random()+1).toString(36).substring(7);
emix 2015年

1を追加しても、ここで説明する2つの問題のどちらも解決されないためです。たとえば、(1).toString(36).substring(7)は空の文字列を生成します。
amichair 2015年

を使用Math.random().toString(36).substring(2,7)すると、より類似した期待される結果が得られます.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 2015年

これは素晴らしいですが、N = 16でFirefoxで実行すると、最後の6桁はゼロになります...(ただし、OPの5つのランダムな文字に対する要望を満たしています)
Edward Newell

128

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

@ x-ray、you get get "0";)
Valentin Podkamennyi

2
丁度。;)そして、結果がMath.random()返さ0.5れる場合は"0.i"です。他のエッジケースがあるかどうかは不明です。これは質問に対する正しい答えではないことを指摘したかっただけです([a-zA-Z0-9]の5文字)。
X線

2
@ x-ray、これが正しい答えであると言うつもりはありません。これは、上の@doubletap答えのコンパクトバージョンであると言っているだけです。私は(+new Date + Math.random())このケースを防ぐために個人的に使用しています。とにかく、メモをありがとう。
Valentin Podkamennyi

1
この。他の回答に多くのコードが必要な理由がわかりません
john ktejik

100

このようなものがうまくいくはずです

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

ここに例のバリアントがあります:mediacollege.com/internet/javascript/number/random.html
David

1
ループ内でlen直接デクリメントすることもできwhileます
drzaus 2013年

おかげで、私はちょうどこの例のCoffeeScriptの変化の下に掲示さ:stackoverflow.com/a/26682781/262379
Dinisのクルス

これらが公的に使用される場合は、おそらく母音を削除する必要があります。エントロピーは少し低くなりますが、人を怒らせるような言葉を生成できないため、はるかに安全です。自分の文字列で送信できるので、これが好きです。よくやった。
Nate Bunney

かなりハードコア、私のために働いた、ありがとう!
Zaki Mohammed

73

es6 スプレッド演算子含む新しいバージョン:

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

  • 30任意の数である、あなたが望む任意のトークンの長さを選ぶことができます
  • これ36は、numeric.toString()に渡すことができる最大の基数です。これは、すべての数字とzの小文字を意味します
  • 2このようになりますランダムな文字列から第3回のインデックスを選択するために使用されます"0.mfbiohx64i"、我々は後に任意のインデックスを取ることができます0.

説明してもらえますか?特に36をtoString()に渡し、なぜ3番目の要素を選択するのですか?
vuza

5
これが最善の解決策です
克服者

いいですが、このソリューションには、要求された質問として[AZ]文字が含まれず、[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));


私はこれが一番好きです。簡単に変更して、追加のパラメーターを受け入れ、nums、lowers、またはcapsのみを返すことができます。超圧縮スタイルが必要だとは思いませんwhile(s.length< L) s+= randomchar();
mastaBlasta 2014年

3
また、それwhile(L--)を実行します
vsync

1
'A'.charCodeAt(0)マジックナンバーよりもロバスト性を使用することをお勧めします55(同様に61)。特に、私のプラットフォームではとにかく、返されるマジックナンバーはです65。そのコードは自己文書化にも優れています。
Grumdrig 2017

ここで実装の縮小最適化(46バイト小さい)バリアントを作成しました:stackoverflow.com/a/52412162
Waruyama

@Waruyamaをデバッグして頑張ってください。それがwebpackの目的です!
ディランワトソン

61

ランダム文字列ジェネレータ(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"


上記では、目的のA / N、A、N出力に対して追加のチェックを使用していますが、理解を深めるために、本質的な要素(英数字のみ)に分解してみましょう。

  • 引数を受け入れる関数を作成します(ランダムなString結果の望ましい長さ)
  • var str = "";ランダムな文字を連結するような空の文字列を作成します
  • ループ内で0から61までのインデックス番号作成しrandます(0..9 + A..Z + a..z = 62)
  • 調整/修正する条件付きロジックを作成し(0..61であるため)、数値をインクリメントして(以下の例を参照)、正しい数値と関連する文字を取得します。randCharCode
  • ループ内で連結し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))


33

最も簡単な方法は次のとおりです。

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

これにより、現在の時刻に基づいて5文字のランダムな文字列が生成されます。出力例は4mtxjor 4mv90または4mwp1

この問題は、同じ秒に2回呼び出すと、同じ文字列が生成されることです。

より安全な方法は次のとおりです。

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

これにより、常に異なる4文字または5文字のランダムな文字列が生成されます。出力例は30jzmor 1r591またはor4su1a

どちらの方法でも、最初の部分は乱数を生成します。.toString(36)一部はそれをbase36(alphadecimal)表現に番号をキャスト。


これがどのように質問に答えるかはよくわかりません。これは7年前の質問で、すでに多くの有効な回答があります。新しい回答を提供することを選択した場合は、回答が十分に説明され、文書化されていることを確認するために、特に注意を払う必要があります。
Claies、2015年

1
:あなたは日付を使用する場合は、なぜあなたは同じようにそれを使用しないでください(+new Date).toString(36)
seniorpreacher

私はあなたの乱数解が好きですが、9e6は5桁(36 ^ 5)の60.4百万の可能性よりも9百万の可能性しか与えないので、それを置き換えるために置き換えることができます(0|Math.random()*6.04e7).toString(36)
Le Droid 2016年

1
暗号的に驚くほどである必要のない、可能な限り短いルーチン(コードデモ用)を備えた長めのランダムな文字列が必要でした。ちょうどいいランダムな視覚的な「ふわふわ」を生成するだけです。私はこの答えが一番好き(あなたの2番目の答え)なので、ありがとう。私の2セント:短くするためにキーストロークを1回減らすことでこれを打ち負かすことができ、通常は13個のランダムな文字(ピリオドなし)を生成します(Math.random()*1e20).toString(36)
アンドリュー・ウィレムス

私がこの答えを持っている一つの欠点は、それが元の質問にある偶然[AZ]を使用しないことです。
user.friendly 2017年

22

ここに簡単なワンライナーがあります。変更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"]();});

20

私は誰もがすでにそれを正しく理解していることを知っていますが、私はこれを可能な限り最も軽量な方法(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の構文の素晴らしさを実際に示していると思います。


20
コードを短くしたいのであれば、なぜ書くcurrent = current ? current : '';ことができるのに、なぜ書くのかcurrent = current || ''
CaffGeek

9
:私たちはここにマイクロ最適化を話しているので、私は実際には変数の代入全く必要でない場合はスキップすることをお勧めcurrent || (current = '');
トーマス・ヘイマン

「良い」がリソースを浪費する再帰アルゴリズムを使用しているときにマイクロ最適化を試みても意味がありません。
Mörre

17

LodashまたはUnderscoreを使用している場合、それはとても簡単です:

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

6
Lodashの使用_.sampleSize('asdfgh',5).join('')
marlo

2
ドキュメントごとに各文字は一意のインデックスからのものであるため、これは実際には良い解決策ではありません。つまり、キャラクターが繰り返すことはできず、繰り返すこともないため、それは本当にランダムではありません。
random_user_name 2017年

16

要件[a-zA-Z0-9]およびlength = 5を使用するには

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

小文字、大文字、数字が出現します。


1
Math.random()は、文字数が少なすぎるbase64文字列になる可能性があると思います。
Leif

14

一度にメモリを割り当てるワンライナー(便宜上、そのようにフォーマットされていませんが)に興味がある場合(ただし、小さな文字列の場合は重要ではないことに注意してください)、その方法を次に示します。

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)


13
あなたがそれをそのようにフォーマットすれば、すべてのjavascriptプログラムは「ワンライナー」です
hacklikecrack

13

これが私が作成したメソッドです。
大文字と小文字の両方を含む文字列を作成します。
さらに、英数字の文字列を作成する関数も含めました。

作業例:
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)));
}

この関数を使用すると、「M」より大きい大文字または「n」より小さい小文字を取得することはできません。
erkanyildiz、2015年

本当に?おお!おそらくそれ以上テストするでしょう。しかし、これはランダムな文字列であり、その中にどんな文字が含まれているかは気にしません(ランダムである限り)。アップグレード、ありがとう。
アダム

12

underscorejsを使用ていると仮定すると、ランダムな文字列を2行だけでエレガントに生成できます。

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

6
これにより、戻り値にはすべて一意の文字が含まれます。また、文字列の長さは可能なvarの長さまでに制限されています。
Yefu

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

シンプルでクリーンなソリューション
Mark Swardstrom

これは大きな+1に値します
Walid Ammar

10

高速で改善されたアルゴリズム。ユニフォームを保証しません(コメントを参照)。

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
正解ですが、確率は均一ではありません。62の可能な文字がありcrypto.getRandomValues、256の一意の値の1つを返します。256は62で除算されないため、文字AHを取得する確率がわずかに高くなります。最善の解決策は、YouTubeが行ったことを実行し、2つの文字(-_)を文字セットに追加することです。とにかく素晴らしい仕事-この回答にはもっと多くの愛が必要です:)
TeWu

追加-および_は、完全なURLセーフのbase64セットを取得するため、優れたアイデアです
cowbert

8

「ランダムな文字列が必要です」という質問(どんな言語でも)に対する応答の問題は、事実上すべてのソリューションが文字列長の欠陥のある主要な仕様を使用していることです。質問自体は、ランダム文字列が必要な理由を明らかにすることはめったにありませんが、長さのランダム文字列が必要になることはめったにありません。たとえば、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」

使用する文字セットの合計文字数の違いによる文字列の長さの違いに注意してください。指定された数の潜在的な文字列で繰り返されるリスクは同じです。文字列の長さは異なります。そして何よりも、繰り返しのリスクと文字列の潜在的な数は明白です。文字列の長さを推測する必要はもうありません。


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

これは可能な限りクリーンです。http://jsperf.com/ay-random-stringも高速です。


私にとっては、これは常にランダムな文字列を生成しますstrLength - 1:-/
xanderiel

3
から--strLengthに切り替えるとstrLength--修正されます。
xanderiel 2013年

7

たとえば、ランダムな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

小文字と大文字の両方をサポートするための明確な解決策が見つかりませんでした。

小文字のみサポート:

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

小文字と大文字をサポートするソリューションを構築します。

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

5in substr(2, 5)を変更して、必要な長さに調整します。


6

一発ギャグ:

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

これを短くするには、引数をArray(15)より小さい値に変更します。例:Array(4)
アンドリュー

シンプルで明確なこのソリューションは本当に気に入っています。0と1の間の15の乱数を生成し、16進数を生成してから、最初の2文字を削除します。最後に、それらすべてをマージします。
Siscia

5

これは確かに機能します

<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

次のようなものはどうでしょう:Date.now().toString(36) ランダムではありませんが、呼び出すたびに短くてユニークです。


1
残念ながら、Date.now()ミリ秒の分解能しかないため、これは一意ではありません。たとえば、単純なループで実行すると、多くの重複が発生します。for (let i = 0; i < 10; ++i) { console.log(Date.now().toString(36)); }
ネイト

5

大文字と小文字を区別しない英数字の文字:

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受け入れられた回答に「いいね!」を追加できると便利です。そのため、関数の結果はより設定可能です。
Denis.Sabolotni 2018年

4

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

4

coderainを使用できます。与えられたパターンに従ってランダムなコードを生成するライブラリです。#大文字、小文字、数字のプレースホルダーとして使用します。

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

A大文字や9数字のような他のプレースホルダーがあります。

便利なのは、呼び出し.next()によって常に固有の結果が得られるため、重複を心配する必要がないことです。

これは、一意のランダムコードのリスト生成するデモアプリケーションです。

完全な開示:私はコードレインの作者です。


いいえいいえいいえ-ネイティブメソッドを使用します。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.