JavaScript で配列の中から最大値・最小値を求める : 異常値を省きつつ…
JavaScript で配列の中から最大値・最小値を求めるには、Math.max.apply()
もしくは Math.min.apply()
という構文が使える。
Math.max.apply(null, [0, 3, 10]);
Math.min.apply(null, [0, 3, 10]);
しかしこれは、言語仕様上、null
・undefined
・NaN
が混じると正しく判定できなくなってしまう。
そこで、配列の中から数値として正しくない値を引っこ抜いて検証することにする。
今回用意した配列はこんなもの。
const array = [-1, -2.2, -Infinity, 0, Infinity, NaN, 1, null, 0xFFFF, 0b1101, 0o3162, undefined, 864e5, 9.99];
null
・undefined
・NaN
が混じっているので、コレを除去したいと思う。なお、Infinity
も入れてあるが、コレもあとで除外できる。
方法1 : Number 関数を利用して NaN を弾く
Number()
関数の引数に値を入れると、数値型に変換できるものは変換し、変換できないものは NaN
にしてくれる。この結果を isNaN()
関数で判定すれば良い。
一つ注意しないといけないのは、Number(null)
は 0
に変換されることだ。コレを回避するため、!== null
な比較は必要。
Array.prototype.filter()
を利用し、配列から条件に合う要素のみ抜き出してみた。
const nums = array.filter((item) => {
return item !== null && !isNaN(Number(item));
});
方法2 : toString()
を確認する
次は、Object.prototype.toString
を call()
で借りて、各要素が [object Number]
を返すかでチェックする。null
は [object Null]
、undefined
は [object Undefined]
を返すのだが、NaN
だけは [object Number]
を返してくるので、最後に !isNaN()
でチェックしている。
const nums = array.filter((item) => {
return Object.prototype.toString.call(item) === '[object Number]' && !isNaN(item);
});
ちなみに、今回の配列の中で isNaN()
が true
になるのは、NaN
と undefined
のみ。null
は false
になる。
Infinity を除外するには isFinite()
方法1・2のどちらでも目的の結果は得られる。速度については気にしていない。
ココからさらに Infinity
や -Infinity
を除外するには、isFinite()
関数を使う。
この関数は、Infinity
と -Infinity
の他に NaN
・undefined
も false
を返すので、null
だけ別に除外して以下のようにチェックすれば良い。
const nums = array.filter((item) => {
return item !== null && isFinite(item));
});
あとはこうして filter()
した要素を Math.max.apply()
や Math.min.apply()
に突っ込めば OK。