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つのステップがあります。
Object.keys()
はオブジェクトのkey-value
ペアからキーの配列を返します。この例ではlinearAlgebra, chemistry, biology, languages
です。Object.keys()
の結果は、フィルタ関数の引数でもあるコールバック関数innerFilterFunction
に送られ、そのinnerFilterFunction
の出力がフィルタリングされた鍵になります。この例では、chemistry, languages
が出力されます。- フィルタの結果は
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}