JavaScriptの配列のメソッドの使い方～forEach・sort・reduce・reduceRight・every・some～

# 記事の目的

どもー、N予備校でプログラミングを勉強中のふーちんです！
この記事ではJavaScript配列関係のメソッドの使い方、6つ紹介・説明しまーす。
`forEach`・`sort`・`reduce`・`reduceRight`・`every`・`some`です！
初心者にもわかりやすく（自分も初心者ですが）説明したつもりです。

# 目次

- [1つ目、forEachメソッド](https://qiita.com/fuuchin/items/8d598cc89721e5520296#foreach)
- [2つ目、sortメソッド](https://qiita.com/fuuchin/items/8d598cc89721e5520296#sort)
- [3つ目、reduceメソッド](https://qiita.com/fuuchin/items/8d598cc89721e5520296#reduce)
- [4つ目、reduceRightメソッド](https://qiita.com/fuuchin/items/8d598cc89721e5520296#reduceright)
- [5つ目、everyメソッド](https://qiita.com/fuuchin/items/8d598cc89721e5520296#every)
- [6つ目、someメソッド](https://qiita.com/fuuchin/items/8d598cc89721e5520296#some)

# forEach

[MDNはこちら](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach)

##### 《 おもなメソッドの役割 》

◎ 配列の全ての要素に`関数を実行する`。（一つ一つの要素をループする感じで）

◎ 第1引数：ループしているときの今の要素
◎ 第2引数：↑のインデックス
◎ 第3引数：配列全体そのもの
を、取得して関数内で使えます。

`for`文使ってもできることですが、このような便利な方法もあります。

呼び出された`元の配列は何も変化しない`。使われるだけ。

```javascript: サンプルコード：旧暦4月まで覚えよう
const monthName = ['睦月', '如月', '弥生', '卯月'];

monthName.forEach(function(item, index, array) {
    console.log(`配列「${array}」の${index}番目の要素は、「${item}」です。`);
});
// 配列「睦月,如月,弥生,卯月」の0番目の要素は、「睦月」です。
// 配列「睦月,如月,弥生,卯月」の1番目の要素は、「如月」です。
// 配列「睦月,如月,弥生,卯月」の2番目の要素は、「弥生」です。
// 配列「睦月,如月,弥生,卯月」の3番目の要素は、「卯月」です。
//             ↑              ↑               ↑・・・引数itemの中身が順番に出てくる
// 引数arrayの中身は配列全体 / 引数indexの中身が順番に出てくる
```
ここの
```javascript
monthName.forEach(function(item, index, array) {
    console.log(`配列「${array}」の${index}番目の要素は、「${item}」です。`);
});
```
のコードを`function`を使わずにアロー関数で実装すると、
```javascript
monthName.forEach((item, index, array) => {
    console.log(`配列「${array}」の${index}番目の要素は、「${item}」です。`);
});
```
こうなります。

# sort

##### 《 おもなメソッドの役割 》

[MDNはこちら](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/sort)

◎ 配列の要素を、`並び替える`

呼び出された`元の配列が変更される`。

```javascript: サンプルコード：小さい順に並び変わるかな？
const num = [18, 1, 3, 26, 8, 77];

num.sort(); // これで数値順に並び変わるはず、、？

console.log(num);
// → [1, 18, 26, 3, 77, 8]　← あれ？順番は変わったけどなんか変
```
なぜこのような順番になったのでしょうか。
実は、`sort`が実行されるときに、数値の要素もすべて`文字列に変換`されるのです。
`sort`は、引数ナシのデフォルトでは、`辞書を引く時の順`（アルファベット順、五十音順）で並べ替えられるのです。

Chromeのデベロッパーコンソールで
```javascript
18 < 3
```
と実行すると、当然結果は`false`です。次に、
```javascript
'18' < '3'
```
と実行すると、結果は`true`になりました。
辞書で引く時のように、`3`よりも`1`の方が早いので、`18`の方が先なのです。

###### ですが、本当に数値順に並べ替えたいときはどうしたらいいのでしょうか。

引数ナシのときに辞書引きの順になるのなら、引数に独自の関数を渡せばいいのです。

```javascript: サンプルコード：これでどや
const num = [18, 1, 3, 26, 8, 77];

function sortFn(a, b) {
  if(a < b) {
    return -1;
  }
  if(a > b) {
    return 1;
  }
  if(a === b) {
    return 0;
  }
}

num.sort(sortFn);

console.log(num);
// → [1, 3, 8, 18, 26, 77]　← ちゃんと数の小さい順に並んだ！
```
これを見て、`a`,`b`ってなんやねん、`-1`,`1`,`0`ってどゆこと？ってなりませんか？
`a`と`b`は、並べ替えるときの比較する配列中の要素です。

次に`-1`,`1`,`0`ってどゆことっていう話ですが、
`return`で負の数値を返すと、`a`が`b`の前に来ます。（`a`の方が小さいときになってほしい）
正の数値を返すと、`a`が`b`の後ろに来ます。（`a`の方が大きいときになってほしい）
`0`を返すと、`a`と`b`の順番は入れ替えません。（`a`と`b`の数が同じときになってほしい）

ややこいので表にまとめました。
| `return`の後 | `a`と`b`の順番 |
|:-:|:-:|
| 0より大 | `b`→`a` |
| 0より小 | `a`→`b` |
| 0 | そのまま |

勘のいいひとはあること思いついたのかもしれません。
`a`が`b`より小さいときには負の数を返せば良く、
`a`が`b`より大きいときには正の数を返せば良く、
同じだったら`0`。
そうです。
`a`から`b`を引けば、いつでもそうなりますよね。
もっと簡単にして、一番簡略化したらこんなコードが出来上がります。
```javascript: サンプルコード：本当にこれでどや
const num = [18, 1, 3, 26, 8, 77];

num.sort((a, b) => a-b);
// アロー関数使わずにやるとこう↓
// num.sort(function(a, b) {
//   return a-b;
// });

console.log(num);
// → [1, 3, 8, 18, 26, 77]　← ちゃんと数の小さい順に並んだ！
```

# reduce

[MDNはこちら](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce)

◎ 引数には関数を渡し、関数は各要素に順番に実行し、その結果を次の呼び出しに`引き継ぐ`ことができる 

これは、reduceの基本のカタチです。
```javascript
let value = arr.reduce(function(accumulator, currentValue, index, arr) {
  // ...
}, initial);
```
関数の引数の説明をします。
- `accumulator` ・ 前の関数呼び出しの結果です。(`acc`っていう表記することもある)
- `initial` ・・・ 0番目では前の関数の呼び出し結果などはないので、これを使う（省略可）
- `currentValue` ・ 順番に見ていくときの現在の配列の項目です。 （`item`とか`current`や`cur`などの表記もあり）
- `index` ・・・・ 順番に見ていくときの現在位置です。（省略可）
- `arr` ・・・・・ 配列そのものを取得できます。（省略可）

そして、最後の要素まで完了したら、`value`に代入されるわけです。
ちなみにですが、いろんな引数の表記があって、引数名は、分かればどんな名前にしてもいいです。
とにかく、1つ目が前の結果、2つ目は現在の要素であるということです。

reduceは、サンプルコードを見れば見るほど理解できるようになる（はず）です。
2つ用意しました。

```javascript:サンプルコード1：合計値を求めるプログラム
let numbers = [5, 3, 2, 7, 3];

let sum = numbers.reduce(function(acc, cur) {
  return acc + cur; // 前の値に現在の要素を足すことを繰り返すことで実装できる。
}, 0); // 最初は0を入れておくことで結果に影響が出ない（省略できるのですが）

console.log(sum); // 20　← 合計値を求められた！
```

```javascript:サンプルコード2：最大値を求めるプログラム
let numbers = [5, 10, 8, 2, 12, 7, 3];

let sum = numbers.reduce(function(acc, cur) {
  if(acc > cur) {
    return acc; // 現在の要素より前の値の方が大きければ、前の値の方を返し、次の関数の呼び出しの`acc`になる。
  } else {
    return cur; // 前の値より現在の要素の方が大きいまたは同じだったら、現在の要素の方を返し、次の関数の呼び出しの`acc`になる。
  }
}); // ここに0を入れてしまうと、配列の中身が負の数だらけだった時に困る

console.log(sum); // 12　← 最大値を求められた！
```
大体わかったでしょうか。
ちなみに、これらのコードをアロー関数などを使って簡潔に書くと、こうなります。

```javascript:合計値の方を簡潔に
let numbers = [5, 3, 2, 7, 3];

let sum = numbers.reduce((acc, cur) => acc + cur);

console.log(sum); // 20　← 合計値を求められた！
```

```javascript:最大値の方を簡潔に
let numbers = [5, 10, 8, 2, 12, 7, 3];

let sum = numbers.reduce((acc, cur) => acc > cur ? acc : cur); // 三項演算子を使って条件分岐
//                                     ↑が真ならば  ↑使う ↑偽なら使う

console.log(sum); // 12　← 最大値を求められた！
```

# reduceRight

[MDNはこちら](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/reduceRight)

◎ `reduce`は0番目から実行するのに対し、これは右から左へと、最後の要素から実行する。
◎ やってることは`reduce`とほとんど一緒

サンプルコードを用意したいのですが、順番が違うことが分かるように、
最大値を求めるプログラムを、毎回コンソールで出力させるように変更して、どうなるかを見てみましょう。

```javascript:reduceで最大値を求める
let numbers = [5, 10, 8, 2, 12, 7, 3];

let sum = numbers.reduce(function(acc, cur) {
  if(acc > cur) {
    console.log('現段階の最大値は' + acc);
    return acc;
  } else {
    console.log('現段階の最大値は' + cur);
    return cur;
  }
});

console.log('最大値は' + sum);

// 現段階の最大値は10
// 現段階の最大値は10
// 現段階の最大値は10
// 現段階の最大値は12
// 現段階の最大値は12
// 現段階の最大値は12
// 最大値は12
```

```javascript:reduceRightで最大値を求める
let numbers = [5, 10, 8, 2, 12, 7, 3];

let sum = numbers.reduceRight(function(acc, cur) {
  if(acc > cur) {
    console.log('現段階の最大値は' + acc);
    return acc;
  } else {
    console.log('現段階の最大値は' + cur);
    return cur;
  }
});

// 現段階の最大値は7
// 現段階の最大値は12
// 現段階の最大値は12
// 現段階の最大値は12
// 現段階の最大値は12
// 現段階の最大値は12
// 最大値は12

console.log('最大値は' + sum); // 12　← 最大値を求められた！
```
順番が違うことは分かったと思います。
でも、このプログラムでは使い分ける必要がないと思ったでしょう。

どんな時に使えるかって、配列などの順番が関係するものを結合させるときに使えそうです。

配列の結合の際には`concat`というメソッドを使います。
`concat`についてはこんな記事も書きました。

https://qiita.com/fuuchin/items/f610049a283d94465bf5#concat
```javascript:配列in配列の結合（reduce）
let numbers = [[0, 1], [2, 3], [4, 5]];

let result = numbers.reduce(function(acc, cur) {
  return acc.concat(cur);
});

console.log(result); // [0, 1, 2, 3, 4, 5]
```

```javascript:配列in配列の結合（reduceRight）
let numbers = [[0, 1], [2, 3], [4, 5]];

let result = numbers.reduceRight(function(acc, cur) {
  return acc.concat(cur); // 現在のアイテム自体が[0, 1]とか[2, 3]とかの配列
});

console.log(result); // [4, 5, 2, 3, 0, 1] ← 逆順なのでこうなる！
```

全然結果が変わりました。
`reduce`分かった人は`reduceRight`も分かったと思います。
ちなみに、先ほどのプログラムをアロー関数などを使って簡潔に書くとこうなります。
```javascript:配列in配列の結合（reduceRight）簡潔版
let numbers = [[0, 1], [2, 3], [4, 5]];

let result = numbers.reduceRight((acc, cur) => acc.concat(cur));

console.log(result);
```

# every

[MDNはこちら](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/every)

◎ 配列のすべての要素が、ある条件を満たすか、`true`か`false`を返す。

```javascript:サンプルコード：全て5以上か
let numbers1 = [6, 7, 8, 5, 5];

let is5over1 = numbers1.every(function(currentValue) {
  return currentValue >= 5;
});

console.log(is5over1); // true ← 全て5以上！

let numbers2 = [6, 7, 4, 5, 8];

let is5over2 = numbers2.every(function(currentValue) {
  return currentValue >= 5;
});

console.log(is5over2); // false ← 4があって、全て5以上ではない！
```
なお、条件を満たすのかどうか、順番に見ていくので、`currentValue`は現在見ている要素のことです。
この引数名は、`current`とか`cur`とかに略すこともありますし、そもそもどんな名前にしても良いです。

それと、アロー関数などを使って簡潔に書くと、こうなります。
```javascript:簡潔に書く
let numbers1 = [6, 7, 8, 5, 5];

let is5over1 = numbers1.every(currentValue => currentValue >= 5);

console.log(is5over1);
```

# some

[MDNはこちら](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/some)

◎ ある条件に、配列の1つ以上の要素が適応するか、`true`か`false`を返す。
`every`と似たことをするのですが、`every`とは違い、1つでも条件を満たせばOKです。

```javascript:サンプルコード：全て5以上か
let numbers1 = [6, 7, 8, 5, 5];

let is5over1 = numbers1.some(function(currentValue) {
  return currentValue >= 5;
});

console.log(is5over1); // true ← 全て5以上！

let numbers2 = [6, 7, 4, 5, 8];

let is5over2 = numbers2.some(function(currentValue) {
  return currentValue >= 5;
});

console.log(is5over2); // true ← 条件を満たさないのは4だけなのでOK！

let numbers3 = [1, 0, 4.5, -3, 4];

let is5over3 = numbers3.some(function(currentValue) {
  return currentValue >= 5;
});

console.log(is5over3); // false ← 1つも条件を満たさないのはさすがにダメ！
```
ちなみに、アロー関数などを使って簡潔に書くと、こうなります。
```javascript:簡潔に書く
let numbers2 = [6, 7, 4, 5, 8];

let is5over2 = numbers2.some(currentValue => currentValue >= 5);

console.log(is5over2);
```

#### 最後に

ほかのメソッドもまた別の記事などに追加していこうと思います。

ありがとうございました～