HOWTO · JavaScript

JavaScript でオブジェクトをフィルタする

このチュートリアルでは、JavaScript でオブジェクトにフィルタをかける方法を説明します。

このページの内容

このチュートリアルでは、JavaScript でオブジェクトをフィルタリングする方法を紹介します。配列データ型の Object と同様の filter メソッドを JavaScript で実装する方法を学びます。

JavaScript でオブジェクトをフィルタするには reduce を使用する

それでは、reduce 関数を使ってオブジェクトをフィルタリングする関数を実装してみましょう。

以下のようなオブジェクトがあるとしましょう。

var grades = {linearAlgebra: 90, chemistry: 95
biology: 90
    languages : 96
}

上のオブジェクトは学生の成績を表しています。このオブジェクトをフィルタリングして、95 点以上の成績を持つ科目のみを取得する必要があります。

var grades = {linearAlgebra: 90, chemistry: 95, biology: 90, languages: 96};

Object.filter =
    function(mainObject, filterFunction) {
  return Object.keys(mainObject)
      .filter(function(ObjectKey) {
        return filterFunction(mainObject[ObjectKey])
      })
      .reduce(function(result, ObjectKey) {
        result[ObjectKey] = mainObject[ObjectKey];
        return result;
      }, {});
}

    console.log('The grades are ', grades);

var targetSubjects = Object.filter(grades, function(grade) {
  return grade >= 95;
});

console.log('Target Subjects are ', targetSubjects);

このオブジェクトをフィルタリングし、95 点以上の成績を持つ科目のみを取得する必要があります。

"The grades are ", {
  biology: 90,
  chemistry: 95,
  languages: 96,
  linearAlgebra: 90
}
"Target Subjects are ", {
  chemistry: 95,
  languages: 96
}

上の例では、Object.filter 関数を Object.filter = function(mainObject, filterFunction) として実装しています。この例のコードを以下のように単純化することができます。

Object.filter = function(mainObject, filterFunction) {
  return Object.keys(mainObject)
      .filter(innerFilterFunction)
      .reduce(reduceFunction, {});
}

この Object.filter 関数を実装するには、主に 3つのステップがあります。

  1. Object.keys() はオブジェクトの key-value ペアからキーの配列を返します。この例では linearAlgebra, chemistry, biology, languages です。
  2. Object.keys() の結果は、フィルタ関数の引数でもあるコールバック関数 innerFilterFunction に送られ、その innerFilterFunction の出力がフィルタリングされた鍵になります。この例では、chemistry, languages が出力されます。
  3. フィルタの結果は reduce() 関数に渡されます。つまり、この例の結果は {chemistry: 95, languages: 96}.

上の例を ES6 の arrow 構文で再現したい場合は、以下のように書き換えることができます。

var grades = {linearAlgebra: 90, chemistry: 95, biology: 90, languages: 96};

Object.filter = (mainObject, filterFunction) =>
    Object.keys(mainObject)
        .filter((ObjectKey) => filterFunction(mainObject[ObjectKey]))
        .reduce(
            (result, ObjectKey) =>
                (result[ObjectKey] = mainObject[ObjectKey], result),
            {});

console.log('The grades are ', grades);

var targetSubjects = Object.filter(grades, (grade) => grade >= 95);

console.log('Target Subjects are ', targetSubjects);

出力:

The grades are  {linearAlgebra: 90, chemistry: 95, biology: 90, languages: 96}
Target Subjects are  {chemistry: 95, languages: 96}

これはカンマ演算子を使って result オブジェクトを返していますが、これを Object.assign に置き換えることもできます。そのため、コードは以下のように書き換えることができます。

Object.filter = (mainObject, filterFunction) =>
    Object.keys(mainObject)
        .filter((ObjectKey) => filterFunction(mainObject[ObjectKey]))
        .reduce(
            (result, ObjectKey) =>
                Object.assign(result, {[ObjectKey]: mainObject[ObjectKey]}),
            {});

JavaScript オブジェクトのフィルタリングに map 関数を使用する

上記の解決策では reduce 関数を用いているが、JavaScript のオブジェクトをフィルタリングするために map 関数を用いることもできます。

Object.filter = function(mainObject, filterFunction) {
  return Object.assign(...Object.keys(mainObject)
                           .filter(function(ObjectKey) {
                             return filterFunction(mainObject[ObjectKey])
                           })
                           .map(function(ObjectKey) {
                             return {[ObjectKey]: mainObject[ObjectKey]};
                           }));
}

上のように reduce 関数を map 関数に置き換え、さらに Object.assign を用いて Object.keys() から .map() までのすべての操作を spread 構文を用いて spread に送ることで、完全な実装は以下のようになるはずです。

var grades = {linearAlgebra: 90, chemistry: 95, biology: 90, languages: 96};

Object.filter =
    function(mainObject, filterFunction) {
  return Object.assign(...Object.keys(mainObject)
                           .filter(function(ObjectKey) {
                             return filterFunction(mainObject[ObjectKey])
                           })
                           .map(function(ObjectKey) {
                             return {[ObjectKey]: mainObject[ObjectKey]};
                           }));
}

    console.log('The grades are ', grades);

var targetSubjects = Object.filter(grades, (grade) => grade >= 95);

console.log('Target Subjects are ', targetSubjects);

出力:

The grades are  {linearAlgebra: 90, chemistry: 95, biology: 90, languages: 96}
Target Subjects are  {chemistry: 95, languages: 96}