ネタのきっかけ
プログラミング学習というか、パズルを解いているときの問題で
「引数の数値 n を受け取り、0 ~ nまでの値にそれぞれ10を掛けた結果の合計を求めよ」
というような問題が出てきました。(問題の内容は変えてます。もうちょいやることあった気がする)
何も考えなければ、for文で書けるんだけど、JavaのIntStream.range(0, 10)のようにして、要素番号だけ取る方法はないのかな?と思ったのがきっかけです。
解決策
次のコードで解決しました。
const rangeArray = [...Array(10).keys()];
コード解説
基本的にはMDNをご覧いただければ、なんですが、簡単に解説。
Array()
この記事ではArray(arrayLength)を使っているため、arrayLength分の要素を持つ配列が生成されます。arrayLength渡すつもりで、数値以外のものを渡すと要素1つの配列が出来上がりますので注意してください。
Array.keys()
配列内の各インデックスのキーを含む新しいArrayイテレーターオブジェクトを返します。この記事のサンプルコードの場合は、0~9のイテレーターオブジェクトが返ります。
…(スプレッド構文)
配列などの反復可能オブジェクトを展開できます。解決策のコードは以下のような形となります。
[...Array(10).keys()]
-> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
サンプルコード
上記のような一部分だけだと、実装イメージがつかないと思われるので、簡単なサンプルコードも書いておこうと思います。
変数を使ったサンプルコード
上述のコードにある「Array(10)」の数値は、事前に変数定義したものでも(当然)動作します。従って、以下のようなコードで動作させることができます。
function main() {
func(100);
}
function func(n) {
// 0 ~ 99の要素番号が取れる。
const rangeArray = [...Array(n).keys()];
rangeArray.forEach(r => console.log(r));
}
やりたかったことに対する解決策のコード
function calc(n) {
return [...Array(n).keys()]
.map(i => i * 10)
.reduce((acc, val) => acc + val);
}
0~9までの数値に順番に10を掛けて、reduceを使って合計値を算出しました。
for文で考えたもの
function calc(n) {
let sum = 0;
for (let i = 0; i < n; i++) {
sum += i * 10;
}
return sum;
}
特に一行処理をさせたいとかなければ、オーソドックスなパターンじゃないかなと思います。
最後に
記事に起こしましたけど、このロジックが欲しいと思ったきっかけは最初に記載したとおり、プログラミングのパズルのようなものを解いている時だったので、実際にはあまり使わないかなぁと思いました。
と思ってたらこんな記事を見つけました。
記事にある通り、確かに読み手のコストは高いですかね…
JavaScript苦手マンな私は、最初何やっているか一層わからなかったし。
keysは未だによくわからんです。
コメント