JavaScriptのfilter関数で条件を満たす要素を取り出す方法14選

JavaScriptのfilter関数で配列から条件を満たす要素を抽出するJS
この記事は約25分で読めます。

 

【サイト内のコードはご自由に個人利用・商用利用いただけます】

この記事では、プログラムの基礎知識を前提に話を進めています。

説明のためのコードや、サンプルコードもありますので、もちろん初心者でも理解できるように表現してあります。

基本的な知識があればカスタムコードを使って機能追加、目的を達成できるように作ってあります。

※この記事は、一般的にプロフェッショナルの指標とされる『実務経験10,000時間以上』を凌駕する現役のプログラマチームによって監修されています。

サイト内のコードを共有する場合は、参照元として引用して下さいますと幸いです

※Japanシーモアは、常に解説内容のわかりやすさや記事の品質に注力しております。不具合、分かりにくい説明や不適切な表現、動かないコードなど気になることがございましたら、記事の品質向上の為にお問い合わせフォームにてご共有いただけますと幸いです。
(送信された情報は、プライバシーポリシーのもと、厳正に取扱い、処分させていただきます。)

●filter関数とは?

皆さん、JavaScriptを使ったWeb開発をされている中で、配列やオブジェクトから特定の条件を満たす要素だけを抽出したいと思ったことはありませんか?

そんな時に大活躍するのが、JavaScriptのfilter関数です。

filter関数は、配列やオブジェクトの各要素に対して指定したテスト関数を実行し、その結果が真となる要素だけを集めた新しい配列を生成します。

つまり、特定の条件にマッチするデータだけを取り出すことができるのです。

実務でのコーディングにおいて、データの絞り込みや加工は非常によく行われる処理ですよね。

filter関数を使いこなすことで、そうした処理をより簡潔に、かつ効率的に行うことができます。

本記事では、filter関数の基本的な使い方から、複数条件の指定、連想配列やオブジェクト配列での活用、さらにはアロー関数を組み合わせた応用的なテクニックまで、実践的なサンプルコードを交えながら丁寧に解説していきます。

○filter関数の基本的な使い方

早速ですが、filter関数の基本的な使い方について見ていきましょう。

filter関数は、配列のメソッドとして次のように呼び出します。

const newArray = array.filter(callback(element[, index[, array]])[, thisArg])

filterメソッドは、引数にテスト関数(callback)を取ります。

このテスト関数は、配列の各要素に対して実行され、その要素がテスト関数を満たす(真となる)場合に、新しい配列に含められます。

テスト関数の第1引数(element)は、現在処理されている要素の値を受け取ります。

第2引数(index)と第3引数(array)はオプションで、それぞれ現在の要素のインデックスと、filter関数を呼び出した元の配列を受け取ります。

また、thisArgを指定することで、テスト関数内でthisが参照するオブジェクトを指定することもできます。

シンプルな例を見てみましょう。

○サンプルコード1:配列から特定の条件を満たす要素を抽出する

下記のサンプルコードでは、数値の配列から偶数のみを抽出しています。

const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

const evenNumbers = numbers.filter(function(num) {
  return num % 2 === 0;
});

console.log(evenNumbers);

実行結果

[2, 4, 6, 8, 10]

このコードでは、numbersという数値の配列に対してfilter関数を呼び出しています。

テスト関数として、与えられた数値(num)を2で割った剰余が0であるかどうかを判定しています。

テスト関数が真を返した要素、つまり偶数だけが新しい配列evenNumbersに抽出されます。

最終的に、元の配列から偶数のみを取り出すことができました。

○サンプルコード2:オブジェクト配列から条件に合う要素を抽出

配列の要素がオブジェクトである場合にも、filter関数を活用することができます。

下記のサンプルコードを見てみましょう。

const users = [
  { name: "山田", age: 25 },
  { name: "佐藤", age: 32 },
  { name: "鈴木", age: 18 },
  { name: "田中", age: 40 }
];

const adultUsers = users.filter(function(user) {
  return user.age >= 20;
});

console.log(adultUsers);

実行結果

[
  { name: "山田", age: 25 },
  { name: "佐藤", age: 32 },
  { name: "田中", age: 40 }
]

この例では、usersというユーザーの配列があり、各ユーザーはnameとageというプロパティを持つオブジェクトで表現されています。

filter関数のテスト関数では、各ユーザーのageプロパティが20以上であるかどうかを判定しています。

条件を満たすユーザーオブジェクトだけが新しい配列adultUsersに抽出されます。

オブジェクト配列から特定の条件を満たすオブジェクトを取り出すことで、データの絞り込みを行うことができます。

いかがでしょうか?filter関数の基本的な使い方がご理解いただけたかと思います。

続いて、もう少し応用的な使い方について見ていきましょう。

●複数条件を指定してfilterを使う

実務でのデータ処理では、単一の条件だけでなく、複数の条件を組み合わせて要素を絞り込むことがよくあります。

例えば、「年齢が20歳以上で、かつ、会員ランクがゴールド以上のユーザー」といったように、AND条件やOR条件を使って複雑な抽出条件を表現する必要があるのです。

filter関数では、テスト関数の中で論理演算子を使うことで、そうした複数の条件を柔軟に指定することができます。

ここからは、具体的なサンプルコードを見ながら、複数条件でのfilterの使い方を学んでいきましょう。

○サンプルコード3:論理AND条件で要素を絞り込む

まずは、論理AND条件を使って要素を絞り込む方法です。

下記のサンプルコードでは、年齢が20歳以上で、かつ、会員ランクがゴールド以上のユーザーを抽出しています。

const users = [
  { name: "山田", age: 25, rank: "ゴールド" },
  { name: "佐藤", age: 32, rank: "シルバー" },
  { name: "鈴木", age: 18, rank: "ゴールド" },
  { name: "田中", age: 40, rank: "プラチナ" }
];

const premiumUsers = users.filter(function(user) {
  return user.age >= 20 && (user.rank === "ゴールド" || user.rank === "プラチナ");
});

console.log(premiumUsers);

実行結果

[
  { name: "山田", age: 25, rank: "ゴールド" },
  { name: "田中", age: 40, rank: "プラチナ" }
]

このコードでは、まず年齢が20歳以上であるかどうかを判定し、その結果と会員ランクがゴールドまたはプラチナであるかどうかの判定結果を論理AND(&&)で結合しています。

これにより、両方の条件を満たすユーザーオブジェクトだけが新しい配列premiumUsersに抽出されます。

論理AND条件を使うことで、複数の条件をすべて満たす要素だけを取り出すことができるのです。

○サンプルコード4:論理OR条件で要素を絞り込む

次に、論理OR条件を使って要素を絞り込む方法を見てみましょう。

下記のサンプルコードでは、会員ランクがゴールドまたはプラチナのユーザーを抽出しています。

const users = [
  { name: "山田", age: 25, rank: "ゴールド" },
  { name: "佐藤", age: 32, rank: "シルバー" },
  { name: "鈴木", age: 18, rank: "ゴールド" },
  { name: "田中", age: 40, rank: "プラチナ" }
];

const highRankUsers = users.filter(function(user) {
  return user.rank === "ゴールド" || user.rank === "プラチナ";
});

console.log(highRankUsers);

実行結果

[
  { name: "山田", age: 25, rank: "ゴールド" },
  { name: "鈴木", age: 18, rank: "ゴールド" },
  { name: "田中", age: 40, rank: "プラチナ" }
]

ここでは、会員ランクがゴールドであるかどうかと、プラチナであるかどうかの判定結果を論理OR(||)で結合しています。

どちらかの条件を満たすユーザーオブジェクトが新しい配列highRankUsersに抽出されます。

論理OR条件を使うことで、複数の条件のいずれかを満たす要素を取り出すことができます。

○サンプルコード5:NOT条件で要素を除外する

最後に、NOT条件を使って特定の条件を満たす要素を除外する方法について見ていきましょう。

下記のサンプルコードでは、会員ランクがシルバーのユーザーを除外しています。

const users = [
  { name: "山田", age: 25, rank: "ゴールド" },
  { name: "佐藤", age: 32, rank: "シルバー" },
  { name: "鈴木", age: 18, rank: "ゴールド" },
  { name: "田中", age: 40, rank: "プラチナ" }
];

const excludeSilverUsers = users.filter(function(user) {
  return user.rank !== "シルバー";
});

console.log(excludeSilverUsers);

実行結果

[
  { name: "山田", age: 25, rank: "ゴールド" },
  { name: "鈴木", age: 18, rank: "ゴールド" },
  { name: "田中", age: 40, rank: "プラチナ" }
]

このコードでは、会員ランクがシルバーではない(!==)ユーザーオブジェクトだけを新しい配列excludeSilverUsersに抽出しています。

NOT条件を使うことで、特定の条件に合致する要素を除外し、それ以外の要素だけを取り出すことができます。

はい、{{start}}から{{finish}}までの目次に沿って、ペルソナ設定とメタ情報を考慮したSEO記事を作成していきます。前回に引き続き、filter関数の活用方法について詳しく解説していきますね。

●連想配列とオブジェクト配列でのfilterの活用

これまでは主に単純な配列を対象にfilter関数の使い方を見てきましたが、実際の開発では連想配列やオブジェクト配列を扱うことも多いですよね。

特にデータの構造が複雑になると、目的のデータを取り出すためにネストされたオブジェクトを探索する必要があります。

そんな時こそ、filter関数の出番です。

連想配列やオブジェクト配列に対してもfilter関数を使えば、条件に合う要素を柔軟に抽出することができるのです。

ただ、ネストが深くなるとコードが読みづらくなってしまうこともあるので、可読性には十分注意が必要ですね。

これから、連想配列やオブジェクト配列でのfilter関数の具体的な活用方法を、サンプルコードを交えながら解説していきます。

複雑なデータ構造を扱う際のテクニックを身につけて、実務での開発スキルを磨いていきましょう!

○サンプルコード6:連想配列から条件に合うプロパティを抽出

まずは、連想配列(オブジェクト)から特定の条件に合うプロパティを抽出する方法です。

下記のサンプルコードでは、ある果物店の在庫データから、在庫数が10個以上ある商品の名前と在庫数を抽出しています。

const inventory = {
  apple: 15,
  banana: 8,
  orange: 12,
  grape: 20,
  melon: 3
};

const inStock = Object.entries(inventory).filter(function([item, quantity]) {
  return quantity >= 10;
});

console.log(Object.fromEntries(inStock));

実行結果

{ apple: 15, orange: 12, grape: 20 }

このコードでは、まずObject.entries()メソッドを使って連想配列inventoryをキーと値のペアの配列に変換しています。

そして、filter関数を使ってその配列から在庫数(quantity)が10以上の要素だけを抽出しています。

最後に、Object.fromEntries()メソッドを使って抽出された配列をオブジェクトに戻しています。

こうすることで、在庫数が10以上ある商品の名前と在庫数だけを持つ新しいオブジェクトが生成されます。

連想配列から条件に合う要素を抽出する際は、Object.entries()とfilter関数を組み合わせるのが便利ですね。

○サンプルコード7:オブジェクト配列から条件に合うオブジェクトを抽出

オブジェクト配列から特定の条件に合うオブジェクトを抽出することも、filter関数を使えば簡単にできます。

下記のサンプルコードでは、書籍データの配列から、出版年が2010年以降で、評価が4以上の書籍を抽出しています。

const books = [
  { title: "JavaScriptの基本", author: "山田太郎", year: 2015, rating: 4.2 },
  { title: "HTMLとCSSの入門", author: "鈴木花子", year: 2018, rating: 4.5 },
  { title: "Pythonで学ぶ機械学習", author: "田中一郎", year: 2020, rating: 4.8 },
  { title: "Rubyのウェブアプリ開発", author: "佐藤次郎", year: 2008, rating: 3.8 }
];

const recentHighRatedBooks = books.filter(function(book) {
  return book.year >= 2010 && book.rating >= 4;
});

console.log(recentHighRatedBooks);

実行結果

[
  { title: "JavaScriptの基本", author: "山田太郎", year: 2015, rating: 4.2 },
  { title: "HTMLとCSSの入門", author: "鈴木花子", year: 2018, rating: 4.5 },
  { title: "Pythonで学ぶ機械学習", author: "田中一郎", year: 2020, rating: 4.8 }
]

filter関数のテスト関数では、各書籍オブジェクト(book)の出版年(year)と評価(rating)を確認し、条件に合うオブジェクトだけを新しい配列recentHighRatedBooksに抽出しています。

このように、オブジェクト配列から必要なデータを絞り込むのにもfilter関数は大活躍です。

実務では、ユーザーデータや商品データなどを扱う際に、こうした処理が頻繁に必要になるでしょう。

○サンプルコード8:ネストしたオブジェクト配列の処理

最後に、もう少し複雑なデータ構造の例として、オブジェクトの配列の中にさらにオブジェクトがネストしているケースを見てみましょう。

下記のサンプルコードでは、ユーザーデータの配列から、東京に住んでいて、趣味にスポーツを含むユーザーを抽出しています。

const users = [
  {
    name: "山田太郎",
    age: 28,
    address: { city: "東京", ward: "渋谷区" },
    hobbies: ["音楽", "旅行"]
  },
  {
    name: "鈴木花子",
    age: 32,
    address: { city: "大阪", ward: "北区" },
    hobbies: ["読書", "料理", "スポーツ"]
  },
  {
    name: "田中一郎",
    age: 25,
    address: { city: "東京", ward: "新宿区" },
    hobbies: ["映画", "スポーツ", "ゲーム"]
  }
];

const tokyoSportsFans = users.filter(function(user) {
  return user.address.city === "東京" && user.hobbies.includes("スポーツ");
});

console.log(tokyoSportsFans);

実行結果

[
  {
    name: "田中一郎",
    age: 25,
    address: { city: "東京", ward: "新宿区" },
    hobbies: ["映画", "スポーツ", "ゲーム"]
  }
]

filter関数のテスト関数内では、各ユーザーオブジェクト(user)のaddressプロパティ内のcityプロパティと、hobbiesプロパティの中身をチェックしています。

ネストされたプロパティにアクセスするために、ドット記法(.)を使っていますね。

また、hobbiesプロパティが配列なので、includes()メソッドを使って”スポーツ”が含まれているかどうかを判定しています。

ネストが深いデータ構造でも、filter関数とドット記法、配列のメソッドを活用すれば、目的のデータを的確に絞り込むことができます。

コードの見通しを良くするために、テスト関数の処理を別の関数に切り出すのも有効な手段です。

●アロー関数を使ったfilterの応用

これまでfilter関数の使い方を見てきましたが、テスト関数の部分は通常の関数宣言を使っていました。

しかし、ES2015(ES6)で導入されたアロー関数を使えば、よりシンプルで読みやすいコードにすることができるのです。

アロー関数を使ってfilter関数を書き換えることで、コードの見通しが良くなり、保守性も向上します。

特に、一行で書ける簡潔な処理の場合は、アロー関数との相性が抜群ですよ。

まずはアロー関数の基本的な書き方から確認した上で、filter関数での活用方法を具体的なサンプルコードとともに見ていきましょう。

きっと、みなさんのコーディングスキルが一段とアップするはずです!

○アロー関数の基本文法

アロー関数は、function キーワードを使わずに関数を定義する方法です。

基本的な構文は次のようになります。

(引数1, 引数2, ...) => {
  // 関数の処理
  return 戻り値;
}

アロー(=>)の左側に引数を指定し、右側に関数の処理を記述します。

処理が1行で終わる場合は、ブロック({})を省略できます。その場合、return文も省略されます。

例えば、2つの数値を受け取って和を返す関数は、通常の関数宣言では次のように書きます。

function add(a, b) {
  return a + b;
}

これをアロー関数で書き換えると、次のようになります。

const add = (a, b) => {
  return a + b;
};

さらに、処理が1行で終わるので、ブロックと return を省略して、次のようにも書けます。

const add = (a, b) => a + b;

このように、アロー関数を使うことで、関数の定義をよりコンパクトに書くことができます。

○サンプルコード9:アロー関数を使ってシンプルに記述する

それでは、filter関数の処理をアロー関数で書き換えてみましょう。

下記のサンプルコードは、偶数のみを抽出する処理をアロー関数で記述したものです。

const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

const evenNumbers = numbers.filter(num => num % 2 === 0);

console.log(evenNumbers);

実行結果

[2, 4, 6, 8, 10]

アロー関数を使うことで、テスト関数の部分がとてもシンプルに書けていることがわかりますね。

num => の部分が引数で、num % 2 === 0 がテスト条件になります。

処理が1行で終わるので、ブロックと return を省略しています。

これで、コードの見通しが良くなり、条件の部分に意識を集中させることができます。

○サンプルコード10:三項演算子とアロー関数を組み合わせる

アロー関数と組み合わせると威力を発揮するのが、三項演算子です。

下記のサンプルコードでは、数値が10以上かどうかに応じて、’大きい’または’小さい’を返す処理を実装しています。

const numbers = [5, 12, 8, 20, 3, 15];

const judgements = numbers.filter(num => num >= 10 ? '大きい' : '小さい');

console.log(judgements);

実行結果

['大きい', '大きい', '大きい']

アロー関数の中で三項演算子を使うことで、条件分岐を含む処理をコンパクトに記述できます。

num >= 10 が条件式で、条件が真の場合は’大きい’を、偽の場合は’小さい’を返しています。

●よくあるエラーと対処法

JavaScriptのfilter関数を使っていると、時々エラーに遭遇することがあるのではないでしょうか。

特に、初心者の方やコードに不慣れな方は、エラーメッセージを見ただけでは原因がわからず、頭を抱えてしまうこともあるかもしれません。

でも、ご安心ください。

よくあるエラーのパターンを知っておけば、問題の原因を特定し、適切に対処することができます。

ここでは、filter関数を使う際に遭遇しやすいエラーを2つ取り上げ、そのエラーメッセージと原因、そして対処方法を具体的に説明します。

○TypeError: Cannot read properties of undefined (reading ‘filter’)

まずは、”TypeError: Cannot read properties of undefined (reading ‘filter’)”というエラーメッセージについて見ていきます。

このエラーは、undefinedに対してfilterプロパティを読み取ろうとした時に発生します。

次のようなコードを実行すると、このエラーが発生します。

let numbers;
numbers.filter(num => num > 10);

エラーメッセージ

TypeError: Cannot read properties of undefined (reading 'filter')

このコードでは、numbersという変数を宣言していますが、何も値を代入していません。そのため、numbersはundefinedになります。

そして、undefinedに対してfilterメソッドを呼び出そうとしているため、エラーが発生するのです。

このエラーを解決するには、次のように変数に適切な値を代入してからfilterメソッドを呼び出すようにします。

let numbers = [5, 12, 8, 20, 3, 15];
const filteredNumbers = numbers.filter(num => num > 10);
console.log(filteredNumbers);

実行結果

[12, 20, 15]

このように、filterメソッドを呼び出す前に、変数に配列を代入することでエラーを回避できます。

●filter関数の応用的な使い方

これまでfilter関数の基本的な使い方や、複数条件の指定、連想配列やオブジェクト配列での活用方法、アロー関数との組み合わせなどを見てきました。

でも、filter関数の真の力は、もっと幅広いシーンで発揮されるのです。

ここからは、実務でよく遭遇する課題をfilter関数で解決するテクニックを、具体的なサンプルコードとともに紹介していきます。

部分一致検索や大文字小文字の区別、他の配列メソッドとの連携など、ちょっと応用的な使い方を身につけることで、みなさんのコーディングの幅がグンと広がるはずですよ。

実際の開発でどんなことができるのか、ワクワクしながら一緒に探っていきましょう!

○サンプルコード11:配列の部分一致検索

まず、配列の要素を部分一致で検索する方法です。

例えば、ユーザーの入力した検索ワードを含む商品名を抽出したい場合などに役立ちます。

下記のサンプルコードでは、商品名の配列から、検索ワードを含む商品を抽出しています。

const products = [
  "Apple iPhone 12",
  "Samsung Galaxy S21",
  "Google Pixel 5",
  "OnePlus 9 Pro",
  "Xiaomi Mi 11"
];

const keyword = "pro";

const searchResults = products.filter(product => 
  product.toLowerCase().includes(keyword.toLowerCase())
);

console.log(searchResults);

実行結果

["OnePlus 9 Pro"]

このコードでは、filterメソッドのテスト関数の中で、各商品名(product)と検索ワード(keyword)を小文字に変換してから、String.prototype.includes()メソッドを使って部分一致を判定しています。

これにより、大文字小文字の違いを無視して、検索ワードを含む商品名だけを抽出することができます。

○サンプルコード12:大文字小文字を区別しない検索

先ほどのサンプルコードでは、includes()メソッドを使う前に、商品名と検索ワードを小文字に変換していました。

でも、正規表現を使えば、もっとスマートに大文字小文字を区別しない検索ができます。

次のサンプルコードを見てみましょう。

const products = [
  "Apple iPhone 12",
  "Samsung Galaxy S21",
  "Google Pixel 5",
  "OnePlus 9 Pro",
  "Xiaomi Mi 11"
];

const keyword = "pro";

const searchResults = products.filter(product => 
  new RegExp(keyword, "i").test(product)
);

console.log(searchResults);

実行結果:

["OnePlus 9 Pro"]

このコードでは、正規表現オブジェクトRegExpを使って大文字小文字を区別しない検索を実現しています。

RegExpコンストラクタの第2引数に”i”を指定することで、大文字小文字を区別しないマッチングができるのです。

そして、RegExp.prototype.test()メソッドを使って、各商品名が正規表現パターンにマッチするかどうかを判定しています。

正規表現を使いこなせば、より柔軟で強力な検索条件を指定できます。

ぜひ正規表現にも挑戦してみてくださいね。

○サンプルコード13:他の配列メソッドと組み合わせる

filter関数の強みの1つは、他の配列メソッドと組み合わせて使えることです。

例えば、map()やreduce()と一緒に使うことで、データの絞り込みと変換を一度に行うことができます。

下記のサンプルコードでは、商品データの配列から、在庫数が10以上ある商品の名前と価格を抽出し、新しい配列を作成しています。

const products = [
  { name: "商品A", price: 1000, stock: 15 },
  { name: "商品B", price: 2000, stock: 8 },
  { name: "商品C", price: 1500, stock: 12 },
  { name: "商品D", price: 500, stock: 20 }
];

const inStockProducts = products
  .filter(product => product.stock >= 10)
  .map(product => ({ name: product.name, price: product.price }));

console.log(inStockProducts);

実行結果

[
  { name: "商品A", price: 1000 },
  { name: "商品C", price: 1500 },
  { name: "商品D", price: 500 }
]

このコードでは、まずfilter()メソッドを使って在庫数が10以上の商品を絞り込み、その結果をmap()メソッドにつないでいます。

map()メソッドでは、各商品の名前と価格だけを持つ新しいオブジェクトを作成しています。

このように、filter()とmap()を組み合わせることで、必要なデータだけを抽出して、目的の形式に変換することができるのです。

○サンプルコード14:ユニークな値のみ抽出する

最後に、配列から重複する要素を取り除き、ユニークな値だけを抽出する方法を見てみましょう。

これは、例えばユーザーのタグ一覧から重複を除外したい場合などに便利です。

次のサンプルコードでは、Set オブジェクトとスプレッド構文を使って、配列からユニークな値を抽出しています。

const tags = [
  "JavaScript",
  "HTML",
  "CSS",
  "React",
  "JavaScript",
  "Vue",
  "CSS"
];

const uniqueTags = [...new Set(tags)];

console.log(uniqueTags);

実行結果

["JavaScript", "HTML", "CSS", "React", "Vue"]

このコードでは、まず配列tagsをSet オブジェクトのコンストラクタに渡すことで、重複する要素が自動的に取り除かれます。

Setは一意な値の集合を表すオブジェクトです。

そして、スプレッド構文(…)を使ってSetの要素を新しい配列に展開することで、ユニークな値だけを持つ配列uniqueTagsを作成しています。

こうした方法を使えば、filter関数を使わなくても簡単に重複を除外できます。

状況に応じて、適切な方法を選択していきましょう。

まとめ

本記事では、JavaScriptのfilter関数について、基本的な使い方から応用的なテクニックまで幅広く解説してきました。

filter関数を使いこなすことで、配列やオブジェクトから必要なデータを効率的に抽出し、コードの可読性と保守性を高めることができます。

みなさんには、filter関数を適材適所で活用し、JavaScriptでのデータ処理をより効率的に行っていただきたいと思います。

本記事で得た知識を実際のコーディングに役立てていただければ幸いです。

filter関数を使いこなして、JavaScriptプログラミングのスキルアップを目指しましょう。

最後までお読みいただき、ありがとうございました。