はじめに
そろそろ新卒一括採用されたエンジニアの研修が終わって配属が始まる時期なので、主に JavaScript 初心者を対象にした記事をひとつ。
初心者に限らず、年次的に中級者くらいでも「何にでも .filter()
を使う人」を割とよく見かけるので、もっといい方法があるということをぜひ覚えていってください。
便利な組み込みメソッド
JavaScript の配列 (["apple", "banana", "cherry"]
のように、複数の値をリスト形式で持つデータ) には、標準で .sort()
、.map()
のようなメソッドが備わっています。
自分で for
文を書くより、間違いなく効率的で分かりやすく、配列に関する処理を書くことができる強力な手段です。例に挙げた以外にも標準で便利な関数が数多く用意されています。
引数に関数を渡して呼び出す「高階関数」と呼ばれる関数なので、使い方に慣れるまで少し時間がかかるかもしれませんが、JavaScript を使うなら必ず身に着けておきたいテクニックです。
.filter()
.filter()
は、配列から条件に一致する要素だけを抽出する組み込みメソッドです。
filter-example.ts
const numbers = [1, 2, 3, 4, 5];
const oddNumbers = numbers.filter(value => value % 2 === 1);
とても汎用的なメソッドなので覚えておいて損はありません。
しかし、便利なメソッドは .filter()
だけではありません!
.find()
.find()
は、配列から条件に一致する最初の要素を取り出します。条件に一致する要素がない場合は undefined
を返します。
find-example.ts
const users = [
{id: '0000', name: 'Taro'},
{id: '0001', name: 'Jiro'},
{id: '0002', name: 'Saburo'}
];
const user = users.find(user => user.id === '0000');
.filter()
と似ていますが、 条件に一致する要素が 1 つ見つかった時点で処理を終了する ので、処理に無駄がありません。.filter()
でも同じ処理はできますが、最初に 'Taro'
を見つけても処理が終わらず、 'Jiro'
や 'Saburo'
にも絞り込み処理をしてしまいます。
以下のような書き方をしていませんか?
find-using-filter-example.ts
const user = users.filter(user => user.id === '0000')[0];
const user = users.find(user => user.id === '0000');
.find()
を使うことでパフォーマンス面が改善するだけでなく、「1 つ見つけたい」という目的が明確になり、.filter()[0]
と比べて可読性も改善します。
.some()
.some()
は、配列の要素のうち 少なくとも1つが条件を満たすかどうか を判定します。条件を満たす要素が1つでも見つかると true
を返し、1つも見つからなければ false
を返します。
some-example.ts
const numbers = [1, 2, 3, 4, 5];
const hasEvenNumber = numbers.some(num => num % 2 === 0);
const users = [
{name: 'Taro', age: 27},
{name: 'Jiro', age: 25},
{name: 'Saburo', age: 22}
];
const hasAdult = users.some(user => user.age >= 18);
条件に一致する要素が1つ見つかった時点で処理を終了する ので効率的です。
以下のような書き方をしていませんか?
some-using-filter-example.ts
const hasAdult = users.filter(user => user.age >= 18).length > 0;
const hasAdult = users.some(user => user.age >= 18);
.every()
.every()
は、配列の 全ての要素が条件を満たすかどうか を判定します。全ての要素が条件を満たせば true
、1つでも満たさない要素があれば false
を返します。
every-example.ts
const numbers = [2, 4, 6, 8];
const allEven = numbers.every(num => num % 2 === 0);
const users = [
{name: 'Taro', age: 22},
{name: 'Jiro', age: 20},
{name: 'Saburo', age: 17}
];
const allAdults = users.every(user => user.age >= 18);
条件を満たさない要素が1つ見つかった時点で処理を終了する ので、こちらも効率的です。
以下のような書き方をしていませんか?
every-using-filter-example.ts
const allAdults = users.filter(user => user.age >= 18).length === users.length;
const allAdults = users.every(user => user.age >= 18);
まとめ
メソッド | 用途 | 戻り値 | 早期終了 |
---|---|---|---|
.filter() |
条件に一致する要素を全て抽出 | 配列 | なし |
.find() |
条件に一致する最初の要素を取得 | 要素 or undefined | あり |
.some() |
条件に一致する要素が1つでもあるか判定 | boolean | あり |
.every() |
全ての要素が条件に一致するか判定 | boolean | あり |
おわりに
配列操作では、目的に応じて適切なメソッドを選択することで、コードの可読性とパフォーマンスの両方を向上させることができます。
特に大きな配列を扱う場合、早期終了する .find()
、.some()
、.every()
を適切に使い分けることで、無駄な処理を削減できます。
最初は慣れないかもしれませんが、これらのメソッドを使いこなせるようになると、より美しく効率的なJavaScriptコードを書けるようになります。ぜひ積極的に活用してみてください!
さらに効率よくコードを書きたい
標準メソッドにはない unique()
や groupBy()
のような汎用的な関数を提供するユーティリティライブラリを導入すると、さらに可読性の高いコードを書くことができます。
型安全でサイズが小さく計算効率の良い Remeda がお勧めです!
Views: 0