配列の最大値を取得する ES2015版

JavaScriptで、配列の最大値を取得する方法について。
最初に答えを書いておくと、Math.max(...targetArray)

旧来はapplyを使うのが主流だった?

Math.max()を使うと、数値の中から最大のものを取得できる。

Math.max(6, 8, 9, 7); // 9

しかしこれは、一つずつ数を渡す必要があり、配列を渡すことは出来ない。
配列でMath.max()を使うにはどうすればいいのか。

applyを使えば解決する。

const array = [3, 8, 7, 2, 5];
Math.max.apply(null, array); // 8

applyの第二引数には配列を渡して使うが、この配列の要素が1つずつ引数として渡される。
そのため、配列を展開してそれを引数として渡す手段として、applyが有用なのだ。

このテクニックは有名らしく、Math.max.apply(null, array);の記法も、「イディオム」とすら言われている。
事実、「JavaScript 配列 最大値」などで調べると、大体これが出てくる。

スプレッド演算子を使う

だがES2015なら、もっとシンプルに書ける。

先程、「配列を展開してそれを引数として渡す手段」と書いたが、ES2015で使えるようになったスプレッド演算子は、まさにそういった使い方が出来る。

const array = [3, 8, 7, 2, 5];
Math.max(...array); // 8

スプレッド演算子そのものの説明はこちら。

オブジェクトの配列から、特定のプロパティの最大値を取得する

次のような、オブジェクトが要素として格納された配列があったとする。

const memberList = [
  { name: 'Tom', age: 20 },
  { name: 'Bob', age: 25 },
  { name: 'Cate', age: 23 },
  { name: 'John', age: 18 },
];

この中から、ageの最大値を取得したい。このようなケースでも、先程の書き方で対応できる。

Math.max(...memberList.map(m => m.age)); // 25

mapageの配列を作り、それをスプレッド演算子で展開してMath.max()に渡している。

プログラマとしての能力

得意気に書いてきたが、今回書いたものは、自分で考えたものでもなければ、自分で調べたものでもない。
職場のコードレビューで教えてもらったものである。

上記の、memberListからageの最大値を取得したい、というようなケースに遭遇した。
その際に自分が書いたのが、以下のようなコード。
Math.max()すら使っていない。

const ages = [];
let maxAge = 0;
for (let i = 0; i < memberList.length; i++) {
  ages.push(memberList[i].age);
}
for (let i = 0; i < ages.length; i++) {
  if (ages[i] > maxAge) maxAge = ages[i];
}
console.log(maxAge);

すぐに、最大値を取得するならMath.max()を使ったほうが分かりやすい、という指摘を受けた。
恥ずかしながらMath.max()を使ったことがなかったので、ネットで調べた。applyを使ったテクニックも、その時に知った。
以下のように書き換えることで、多少は見通しがよくなった。

const ages = [];
for (let i = 0; i < memberList.length; i++) {
  ages.push(memberList[i].age);
}
console.log(Math.max.apply(null, ages));

だがこれでも不十分だった。
mapとスプレッド演算子を使ったやり方を教えてもらい、それに書き換えた。

console.log(Math.max(...memberList.map(m => m.age)));

俺が9行もダラダラと書いてきたことを、たった1行で表現してしまっている。
可読性や保守性を犠牲にしてトリッキーなことをしている訳でもないのに。

いくらES2015の機能を知っていたとしても、使い方が分からなければ意味がない。
そのことを思い知らされた。
慣れもあるとは思う。場数を踏むことで、すぐに適切なコードが思い浮かぶようになる、というのはあるはず。
だがそれにしても、mapやスプレッド演算子を使えばいいなんて、ちょっと考えればすぐに分かりそうなものなのに。

知識がたくさんあるのは大事だし、いわゆるベストプラクティスを知っていることも大事。
でもそれだけじゃなく、使いこなす能力というか、解決すべき問題は何で、どのようにアプローチすべきで、そのためにどの道具を使えばいいのか、ということを考える能力が必要なんだろう。それこそが、プログラマの能力のような気がする。
思考力とか認識力のようなもの。

後は、やっぱり実務経験が大切というか、ネットで調べて得たものよりも遥かに妥当な内容がコードレビューで返ってきて、笑ってしまった。
いくらプログラミングはネットで独学しやすいとはいえ、優秀な人と一緒に働くほうが、はるかに成長効率がよい。