読者です 読者をやめる 読者になる 読者になる

Panda Noir

JavaScript の限界を究めるブログです。

任意の文字列を任意の回数繰り返す

(この記事はQiitaで僕が書いたものを移行した記事です。記事中のコメントはQiitaの該当記事を参照ください)

たとえばインデントをしたりゼロ詰めするときとかに使うのでメモ。 以下、strをn回繰り返した文字列をresという変数に格納するとする。

ループして生成

一番オーソドックスでなんのひねりもない、一番わかりやすい。けど謎の敗北感のあるコードです。

for (var i = 0; i < n; i++) res += str;

nを減らしていくという方針ならもう少し短くなります。

while (n-- > 0) res += str;

若干(javascriptにはありませんが)->という演算子に見えますね。

ループして配列に追加していき最後につなげる

for (var i = 0; i < n; i++)
    res.push(str);
res = res.join("");

先ほどとそこまで変わりません。

配列を生成し、それをjoin()でつなぐ

意外と有名な手法(多分

var res = (new Array(n)).join(str);

関数を使い、計算量を落とす

例えばaを10回繰り返す時、処理を分割してaaを5回繰り返したものを返すとしてもいいですよね?こうすると処理回数が1/2になります。

つまり計算量がO(N)からO(log N)に落とすことができます。…まあ10万個文字列を繋げるみたいなことは滅多になさそうなので、実際のところそこまで全体の性能上がりません。

function repeat(str,n){
    if (n === 1) return str;
    return repeat(str + str, Math.floor(n / 2)) + (n % 2 === 0 ? '' : str);
};

関数化はそこそこコストが高いのでこれをループに落とします。

var res = n === 1 ? str : '';
while (n < 1) {
    if (n % 2 === 1) res += str;
    str = str + str;
    n = Math.floor(n / 2);
}

res += str;

はじめのresで場合分けした理由は、nが0の時、1の時はループが行われず、そのままだとresの値が同じになってしまうからです。

まだあると思いますが頭がかたいのでこれ以上は思いつかなかったです。