ES6以降のJavaScript/TypeScriptで0...N-1の配列を作る


動機

JavaScript/TypeScriptで定数(N)で決められた数だけループしたい時、

const N = 100;
for(let i = 0; i < N; i++){
   //...なんか処理
}

こんなダサいループは書きたく無い。。。

pythonのrange(N)みたいなのがJavaScriptにもあったらなぁ。。。

解決策

英語でググってみたらStackOverflowに良い解決策が載っていたのでご紹介。

世界には頭の良い人がいるものだなぁ。

const N = 100;
[...Array(N).keys()].forEach(i => {
   //...なんか処理(iには0...N-1(=99)が格納される)
});

もし1...Nにしたければ、

const N = 100;
[...Array(N).keys()].map(n => n + 1); // [1,2,3,...,100]

こんな具合にmapしてズラしてあげればOK。

応用

ということはもしかして、FizzBuzzがワンライナーで書けるんじゃないか...?

[...Array(100).keys()].map(n => n + 1).map(n => n % 15 === 0 ? 'FizzBuzz' : n % 3 === 0 ? 'Fizz' : n % 5 === 0 ? 'Buzz' : n.toString()).forEach(s => console.log(s));

出来た。

一応解説すると、

[...Array(100).keys()] // [0,1,2, ... ,99]の配列を作る
   .map(n => n + 1)    // mapでズラして[1,2,3, ... , 100]にする
   .map(n => n % 15 === 0 ? 'FizzBuzz' : n % 3 === 0 ? 'Fizz' : n % 5 === 0 ? 'Buzz' : n.toString()) // FizzBuzzのルールを満たすように文字列に変換する
   .forEach(s => console.log(s)); //1行ずつ出力する

この.map().forEach()を繋げて書く表記に慣れていない方は、手前味噌で恐縮ですが私の過去記事をご覧ください。

(ちなみに)indexを使用しない場合

生成した配列の中身の数値を使わず、単にN回ループしたい場合は[...Array(N)]で良いらしい。

// 長さが100の0から99までのランダムな整数の配列を作成
const randomInt = [...Array(100)].map(() => Math.floor(Math.random() * 100));

追記(2020/09/22)

この記事に対して別途SNSで頂いたコメントを元に続きを書きました。
ぜひ合わせてご一読ください。

なぜ我々は頑なにforを避けるのか