配列について色々と
配列の初期化
まずは基本的な宣言
const arr = [];
配列の大きさを指定して初期化もしたい…って時はこう。
const arr = Array(10).fill(0); [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
うーん、連番が欲しいなあって時…。
const arr = [...Array(10).keys()]; [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
今の所、初期化で2,3つ目を使うことは無いのですが、後述するループを回すときに必要になって使ったりしています。
配列のループ
for(;;)
プログラミング本で最初に習うループ
添え字やらループ数の指定で誤ることが多く、最近は使うことはないです。
私はこれ書くとき毎回間違えます。今も記事書く前間違えました。
const arr = [1,2,3,4,5]; for(let i = 0 ; i < arr.length ; i++){ console.log(arr[i]); }
forEach
配列を1個ずつ取り出して、関数を実行します。戻り値はありません。 今の現場はこれが多い。 注意点としては、ループを途中で抜けたり、promiseを使った時のawaitができなかったりします。 ループ構文ではなく、あくまで配列のメソッド。
const arr = [1,2,3,4,5]; arr.forEach((value)=>{ console.log(value); }); 'indexもつけられるよ arr.forEach((value,index)=>{ console.log(value); });
for of
こちらもまた、1つずつ取り出してループします。
forEachとは違い、ループ構文なので途中で抜けたりできます。
ただ、indexをつけるときはちょい工夫がいります。
const arr = [1,2,3,4,5]; for(const value of arr){ console.log(value); } 'indexあり for(const [index,value] of arr.entries()){ console.log(value); }
基本的にfor...ofで、indexが欲しいときはforEachを使った方が綺麗なんじゃないかなぁと思います。実際はどうなのかな…。
map,filter
今回の開発で大活躍だったはずのmapとfilter。
既存コードが殆ど配列にpushやらしていたので、それに倣ってcommitしていました。
が、色々調べてるとこっちで書いた方が絶対良いよな…ということで、実装とテストが終わった後、空き時間でひたすら勉強がてら書き換えていました。
commitされるのはこっちじゃないけどね!ただ、書き換える前のコードをメンテするの大変だろうな…。実際配属されてコード読んでた時大変だったし。
map
配列の要素を1つずつ取り出して、関数を実行した後、実行後の配列を返す。 以下は要素を2倍して返しています。
const arr = [1,2,3,4,5]; const result = arr.map((value)=>{ value*2 });//[2,4,6,8,10] `一行だけなら色々省略して書けます const result = arr.map(value=>value*2);
最初の初期化は、mapを書いてるときに必要になりました。
指定の数だけmap回して配列作りたいんだけど…。ってことで、以下のように書いてみると、これが回らない。
Array(5).map((value)=>{ return "なんかの処理"; });
Array(5)は要素を確保するだけで、中身は無いからmapが回らない。
ってことで、mapを回すときどうすりゃいいのかと調べた結果がこれ。
fill(0)で全部初期化して5回のループができる。
Array(5).fill(0).map((value)=>{ return "なんかの処理"; });
こんな書き方ができるんだなーって思ってた所、0での初期化ではなく、連番も欲しくなりました。
ということで、初期化で連番を生成して回すにはこう。
const arr = [...Array(5).keys()].map(value=>value*2); //[0, 2, 4, 6, 8]
ただ、連番だけならmapはindexを持つので、そっちを使ってもいいかも。
const arr = Array(5).fill(0).map((_,index)=>index);
1~の連番を生成したいなら、インクリメントをしたらOK。
const arr = [...Array(5).keys()].map(value=>++value); //[1, 2, 3, 4, 5]
少しmapとは話はずれますが、forループを回すときにも便利に使えますね。
for(const value of [...Array(5).keys()]){ console.log(value); }
filter
配列をひとつずつ取り出して、一致した要素の配列を返す。 こちらもとっても便利。
const arr = [1,2,3,4,5]; const result = arr.filter(value=>value%2===0); //[2, 4]
filterとmapをつなげられるので、filterした結果にmapで何か処理ができます。(その逆も)
const arr = [...Array(5).keys()].map(value=>value*2).filter(value=>value>5); //[6,8]
終わり
いっぱい書いて疲れた。
何か処理をして配列を生成したいなら、mapやfilterを!こっちの方が処理が明示的で読みやすい!