プログラムを書いていると特定の文字や文字列を n回繰り返した文字列を作成したい場合が時々ある。
C#の場合ならこんな感じか。
// C#で文字列を5回繰り返した文字列を作成 string s = String.Concat(Enumerable.Repeat("abc", 5)); // "abcabcabcabcabc" になる
一文字を繰り返すならこういう書き方も出来る。
// C#で1文字を5回繰り返した文字列を作成 string s = "".PadLeft(5, 'a'); // "aaaaa" になる
さて、ワテが最近よく使っているJavaScriptやTypeScriptでも文字列を繰り返した文字列を作成したくなったので少し調べてみた。
では、本題に入ろう。
JavaScript/TypeScript文字列を指定回数だけ繰り返した文字列を作成
まず、上でみたC#と類似の
'abc'.repeat(10)
のような方法がJavaScriptにも有るのか無いのか調べてみたら、有った。
この説明によると、
String.prototype.repeat()
と言うのが有るのだが、でもそれは新しいECMAScript 6の仕様で定義されたようだ。
なので本日(2016/11/25)の時点でのブラウザー実装状況を見てみると、
デスクトップ
機能 | Chrome | Firefox (Gecko) | Internet Explorer | Opera | Safari |
---|---|---|---|---|---|
基本サポート | 41 | 24 (24) | 未サポート | 未サポート | 9 |
モバイル
機能 | Android | Chrome for Android | Firefox Mobile (Gecko) | IE Mobile | Opera Mobile | Safari Mobile |
---|---|---|---|---|---|---|
基本サポート | 未サポート | 36 | 24.0 (24) | 未サポート | 未サポート | 未サポート |
殆どサポートしていない。
と言う事で、自分で何らかの手法を使って文字列を繰り返す関数を作る事にしてみた。
二つの方法を見付けた。
一つ目はスタックオーバーフローで見つけたコード
function repeatStr1_Henteko(str: string, len: number) { //【文字列を指定回数だけ繰り返した文字列を作成する①】 // stackoverflowで見つけたヘンテコな方法 // Create a string of variable length, filled with a repeated character // http://stackoverflow.com/questions/14343844/create-a-string-of-variable-length-filled-with-a-repeated-character var strRepeat = new Array(len + 1).join(str); // 他の人のコメントでは、Note, this solution is VERY slow. と言う事なので使わないほうが良いかも。 return strRepeat; }
なんだかヘンテコな手法なので、なぜこれで文字列をリピート出来るのかワテには良く分からない。
二番目は上記のmozilla.orgにあるString.prototype.repeat()のコードをそのまま流用
function repeatStr2_ES6(this_: string, count: number) { //【文字列を指定回数だけ繰り返した文字列を作成する②】 // String.prototype.repeat() // このメソッドは、ECMAScript 6 仕様で追加されたため、 // まだすべての JavaScript 実装で使用できるわけではありません。 // しかし、次のスニペットで String.prototype.repeat() をポリフィルできます: // https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/repeat 'use strict'; if (this_ == null) { throw new TypeError('can\'t convert ' + this_ + ' to object'); } var str = '' + this_; count = +count; if (count != count) { count = 0; } if (count < 0) { throw new RangeError('repeat count must be non-negative'); } if (count == Infinity) { throw new RangeError('repeat count must be less than infinity'); } count = Math.floor(count); if (str.length == 0 || count == 0) { return ''; } // Ensuring count is a 31-bit integer allows us to heavily optimize the // main part. But anyway, most current (August 2014) browsers can't handle // strings 1 << 28 chars or longer, so: if (str.length * count >= 1 << 28) { throw new RangeError('repeat count must not overflow maximum string size'); } var rpt = ''; for (;;) { if ((count & 1) == 1) { rpt += str; } count >>>= 1; if (count == 0) { break; } str += str; } // Could we try: // return Array(count + 1).join(this_); return rpt; }
こちらのコードは、まあ、地道に文字列を指定回数だけ連結しているのかな。
最初のヤツは他の人のコメントでは速度が遅いと書いてあったので、念のために両者の速度を比較してみた。
文字列繰り返し関数の速度比較
function test2_performance() { const imax = 1000000; { var t1 = performance.now(); for (var i = 0; i < imax; i++) { var repeatStr = repeatStr1_Henteko('abc', 10); } var t2 = performance.now(); var msg = 'elapsed1 = ' + (t2 - t1) + '[ms] ->' + repeatStr + '<-' console.log(msg); alert(msg); } { var t1 = performance.now(); for (var i = 0; i < imax; i++) { var repeatStr = repeatStr2_ES6('abc', 10); } var t2 = performance.now(); var msg = 'elapsed2 = ' + (t2 - t1) + '[ms] ->' + repeatStr + '<-' console.log(msg); alert(msg); } /* elapsed1 = 1799.603686900356[ms] ->abcabcabcabcabcabcabcabcabcabc<- elapsed2 = 1051.8635029534666[ms] ->abcabcabcabcabcabcabcabcabcabc<- */ }
100万回のループ処理の要した時間は以下の通り。
elapsed2 = 1051.8635029534666[ms] ->abcabcabcabcabcabcabcabcabcabc<-
う~ん、確かに後者のmozilla.orgにあるString.prototype.repeat()のほうが倍近く速い。
まとめ
と言う事で、JavaScriptやTypeScriptに於いて、指定した文字列を指定回数繰り返した文字列を作成する処理に関しては、
ワテの場合は当面はこのmozilla.orgにあるString.prototype.repeat()を使う事にする。
何となく本三兄弟。
深い意味は無い。
コメント