JavaScriptで複数の条件に基づいてJSONデータをグループ化し平均値を計算する方法
フロントエンド開発では、APIから取得したJSONデータを特定の条件で集約し、統計値を算出する処理が必要になることがよくあります。本記事では、複数のフィルター条件(「SupplierName」と「Category」)に基づいてオブジェクトの配列をグループ化し、ポイントの合計値と平均値を計算するJavaScriptの実装方法を、サンプルコード付きでわかりやすく解説します。
元データのサンプル
まず、以下のようなサプライヤーの評価データを含む配列を想定します。あえて、Pointsがundefinedになっている不正なレコードも含めています。
const arr = [
{ "SupplierName": "John", "Category": "A", "Points": 3 },
{ "SupplierName": "John", "Category": "A", "Points": 11 },
{ "SupplierName": "John", "Category": "A", "Points": undefined },
{ "SupplierName": "John", "Category": "B", "Points": 2 },
{ "SupplierName": "John", "Category": "B", "Points": 6 },
{ "SupplierName": "Praveen", "Category": "A", "Points": 3 },
{ "SupplierName": "Praveen", "Category": "A", "Points": 7 }
];
実現したい処理
この配列を受け取る関数には、次の役割を持たせます。
- 同じ「SupplierName」と「Category」の組み合わせを持つオブジェクトを、1つのユニークなオブジェクトにまとめる
- 各グループのポイント(Points)を合計する
- 各オブジェクトに新たな「Average」フィールドを追加し、そのグループの平均ポイントを格納する
- Pointsがundefinedなどの無効な値であるレコードは、集計対象から除外する
期待される出力
最終的な出力は次のようになります。
const output = [
{ "SupplierName": "John", "Category": "A", "Points": 14, "Average": 7 },
{ "SupplierName": "John", "Category": "B", "Points": 8, "Average": 4 },
{ "SupplierName": "Praveen", "Category": "A", "Points": 10, "Average": 5 }
];
実装コード
以下が実際のコードです。Array.prototype.reduce()を使ってグループ化を行い、その後で平均値を計算しています。
const groupAndAverage = (arr = []) => {
const groups = arr.reduce((acc, obj) => {
// SupplierNameとCategoryを組み合わせてユニークなキーを生成
const key = `${obj.SupplierName}_${obj.Category}`;
if (!acc[key]) {
// グループが存在しない場合は新規作成
// Averageはこの段階ではカウンターとして使用する
acc[key] = {
SupplierName: obj.SupplierName,
Category: obj.Category,
Points: 0,
Average: 0
};
}
// 有効な数値のみ集計(undefinedやnullは除外される)
if (obj.Points) {
acc[key].Points += obj.Points;
acc[key].Average++;
}
return acc;
}, {});
// 合計ポイントを件数で割り、四捨五入して平均を求める
return Object.values(groups).map(group => ({
...group,
Average: Math.round(group.Points / group.Average)
}));
};
console.log(JSON.stringify(groupAndAverage(arr), undefined, 4));
実行結果
コンソールには以下が出力されます。
[
{
"SupplierName": "John",
"Category": "A",
"Points": 14,
"Average": 7
},
{
"SupplierName": "John",
"Category": "B",
"Points": 8,
"Average": 4
},
{
"SupplierName": "Praveen",
"Category": "A",
"Points": 10,
"Average": 5
}
]
コードの解説
- キーの生成:
reduce()のコールバック内で、SupplierNameとCategoryをアンダースコアで連結した文字列(例:John_A)をグループ識別用のキーとしています。これにより、2つの条件を組み合わせた複合フィルターが実現できます。 - グループの初期化: 同じキーがまだ存在しない場合は、Pointsを0、Averageを0で初期化した新しいオブジェクトを作成します。Averageは最初の段階では「有効なレコード数」のカウンターとして機能します。
- 無効値の除外:
if (obj.Points)という条件により、undefinedやnullといった無効な値を持つレコードは、合計にも件数にも含まれません。そのため、平均値の精度が保たれます。 - 平均の算出: 最終段階で
Object.values()ですべてのグループを取り出し、合計ポイントをカウントで割った値をMath.round()で四捨五入しています。
応用のヒント
小数点以下の値も保持したい場合は、Math.round()の代わりに.toFixed(2)などを利用するとよいでしょう。また、グループ化の条件がさらに増える場合でも、キー生成の部分に条件を追加するだけで柔軟に拡張できます。大量のデータを扱うケースでは、通常のオブジェクトの代わりにMapを使うと、キー名の衝突を気にせず安全に管理できます。
-
JavaScriptでtextareaに入力されたJSONデータを整形(プリティプリント)する方法
textareaに入力されたJSONデータを整形(プリティプリント)して表示するには、JSON.parse()とJSON.stringify()を組み合わせて使用します。まずJSON.parse()で文字列をJavaScriptオブジェクトに変換し、その後JSON.stringify()の第3引数にインデント幅(例:4)を指定することで、インデントが整った読みやすいJSON文字列を取得できます。サンプルコード<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF
-
Excelで複数の条件に基づいてテーブルからデータを抽出する方法
必要なタイミングでデータを取り出せることは、スプレッドシートを活用するうえで最も重要な要素です。Excelも例外ではありません。私たちはデータを表形式でExcelに保存し、必要に応じてそれらを抽出します。本記事では、複数の条件(criteria)に基づいてテーブルからデータを抽出する方法を詳しく解説します。 まずはじめに、例のベースとなるデータセットを確認しておきましょう。 ここには、ジャンル・主演俳優・公開年とともに映画のリストがまとめられたテーブルがあります。このデータセットを使用して、複数の条件に基づいたデータ抽出を行います。 なお、説明をシンプルにするために基本的なテーブルを使用して