[JavaScript] 配列の最小値・最大値を求める
目的
以下のように配列があったとして、その中で最も小さい値・最も大きい値を取り出したい。
[1, 3, 8, 7, 5] // 最小値は1, 最大値は8
解決法
Array.reduce
を使用する。
const arr = [1, 3, 8, 7, 5];
// Array.reduce に渡すコールバック関数
const getMin = (a, b) => Math.min(a, b);
const getMax = (a, b) => Math.max(a, b);
// 実際に求める
const min = arr.reduce(getMin);
const max = arr.reduce(getMax);
console.log(min, max); // 1 8
解説
Array.reduce
は、配列のそれぞれの要素に対して引数に渡されたコールバック関数を実行し、配列を「縮小」していく、JavaScript が提供する関数のひとつです。
こういった、引数に関数を返す・もしくは関数を帰り値とする関数のことを 高階関数(こうかいかんすう) と呼びます。有名なものに map
、 filter
などがありますね。
さて、Array.reduce
の動作のイメージを掴むため、簡単なサンプルを見てみます。以下は、配列の総和を求めるためのサンプルコードです。
const array1 = [1, 2, 4, 5];
const sumAll = array1.reduce(
(sum, now) => sum + now
);
console.log(sumAll); // 12
今回は、Array.reduce
に以下のような関数が渡されているのがわかります。
(sum, now) => sum + now
Array.reduce
は、まず配列の左から2つを取ってコールバック関数に代入します。今回の場合、sum
に 1
、now
に 2
ですね。
(sum, now) => 1 + 2
当然、結果は 3
となります。ここからが重要で、二回目以降は 前回の結果と次の値 を引数として代入します。ここでいう「前回の結果」は 3
、「次の値」は 4
になるので、以下のようになりますね。
(sum, now) => 3 + 4
結果は 7
。次の値は 5
なので、以下のようになります。
(sum, now) => 7 + 5
結果は 12
ですね。
次の値がなくなれば、Array.reduce
は処理を止め、結果を返します。そのため、答えとして 12
が返るわけです。
このように、最終的に単一の値が返るため「縮小」(reduce)なんですね。
ここまでを踏まえて、最大値・最小値のコードを見ます。
const arr = [1, 3, 8, 7, 5];
// Array.reduce に渡すコールバック関数
const getMin = (a, b) => Math.min(a, b);
const getMax = (a, b) => Math.max(a, b);
// 実際に求める
const min = arr.reduce(getMin);
const max = arr.reduce(getMax);
console.log(min, max); // 1 8
重要なのはここですね。
// Array.reduce に渡すコールバック関数
const getMin = (a, b) => Math.min(a, b);
const getMax = (a, b) => Math.max(a, b);
さきほどのイメージに当てはめると、「配列の中の要素を次々に Math.min
もしくは Math.max
に代入する操作」 ということがわかります。Math.min
、Math.max
はそれぞれ与えられた引数の中で最も小さい・大きい数値を返す関数なので、 「配列の要素を2つずつ比較して、より小さい・大きい方を残す」 という操作だといえます。
Discussion
Math.min()
/Math.max()
使うならMath.min(...arr)
/Math.max(...arr)
でいいのでは……?コメントありがとうございます🫶
配列のサイズが小規模であると断定できる場合は、ご指摘の通りスプレッド構文が有効ですね!
ただし、実行環境によっては関数の引数の数に上限が設けられる場合があります。こういった場合
Array.reduce
のほうが有効であるため、最もつつがない方法として取り上げています確かに!ありがとうございます!