JavaScript
 Computer >> コンピューター >  >> プログラミング >> JavaScript

JavaScriptでオブジェクト配列をキーごとにグループ化して値を集約する方法

問題の概要

次のようなオブジェクトの配列があるとします。

const arr = [
    { 'name': 'JON', 'flight':100, 'value': 12, type: 'uns' },
    { 'name': 'JON', 'flight':100, 'value': 35, type: 'sch' },
    { 'name': 'BILL', 'flight':200, 'value': 33, type: 'uns' },
    { 'name': 'BILL', 'flight':200, 'value': 45, type: 'sch' }
];

ここで求められているのは、このような配列を受け取るJavaScript関数を書くことです。関数は各オブジェクトから「value」と「type」というキーを取り除き、その代わりに「type」の値(unsやschなど)を新しいキーとして、「value」の値を対応する値としたキーバリューのペアを追加します。

したがって、上記の入力に対する期待される出力は次のようになります。

const output = [
    { 'name': 'JON', 'flight':100, 'uns': 12, 'sch': 35 },
    { 'name': 'BILL', 'flight':200, 'uns': 33, 'sch': 45 }
];

コード例

この処理を実現するコードは以下の通りです。

const arr = [
    { 'name': 'JON', 'flight':100, 'value': 12, type: 'uns' },
    { 'name': 'JON', 'flight':100, 'value': 35, type: 'sch' },
    { 'name': 'BILL', 'flight':200, 'value': 33, type: 'uns' },
    { 'name': 'BILL', 'flight':200, 'value': 45, type: 'sch' }
];
const groupArray = (arr = []) => {
    const res = arr.reduce(function (hash) {
        return function (r, o) {
            if (!hash[o.name]) {
                hash[o.name] = { name: o.name, flight: o.flight };
                r.push(hash[o.name]);
            }
            hash[o.name][o.type] = (hash[o.name][o.type] || 0) + o.value;
            return r;
        }
    }(Object.create(null)), []);
    return res;
};
console.log(groupArray(arr));

コードの解説

このコードのポイントは、Array.prototype.reduce()メソッドの使い方です。reduceの初期値として空の配列を渡しつつ、クロージャ経由で「name」をキーとしたハッシュマップ(Object.create(null)で生成されたプロトタイプを持たないプレーンなオブジェクト)を保持しています。

  • ハッシュマップの役割: 同じ「name」を持つオブジェクトがすでに生成済みかどうかを高速に判定できます。
  • 新規登録: 初めて登場する「name」であれば、nameとflightを含む新しいオブジェクトを作成し、結果配列にpushします。
  • 値の集約: 既存のオブジェクトに対しては、「type」の値(unsやsch)をキーとして「value」を加算していきます。これにより、同一name・同一typeの値は自動的に合計されます。

実行結果

コンソールには次のように出力されます。

[
    { name: 'JON', flight: 100, uns: 12, sch: 35 },
    { name: 'BILL', flight: 200, uns: 33, sch: 45 }
]

このように、元の配列にあった「value」と「type」のキーが消え、typeの値がキーとなり、それぞれのvalueが集約された新しい構造の配列が得られます。この手法は、APIレスポンスの整形やレポート用データの集計、フロントエンドでの表示データ変換など、さまざまな場面で応用できる便利なパターンです。

  1. JavaScriptのWeakMapオブジェクトとは?基本の使い方をサンプルコード付きで解説

    WeakMapは、キーと値のペアを要素として持つオブジェクトです。通常のMapとの大きな違いは、キーに必ずオブジェクトを指定しなければならないという点です。値にはプリミティブ型(文字列や数値など)でもオブジェクトでも何でも格納できます。 さらに重要な特徴として、WeakMapのキーとして使用されたオブジェクトへの参照が他に存在しなくなると、そのオブジェクトはガベージコレクション(GC)によって自動的にメモリから解放されます。これにより、メモリリークを防ぎながら一時的なデータを安全に関連付けることができます。 WeakMapの主な特徴 キーにはオブジェクトのみ指定可能(プリミティブ値はキーにで

  2. JavaScriptのMap(マップ)オブジェクトとは?基本的な使い方をサンプルコード付きで解説

    MapオブジェクトとはMap(マップ)オブジェクトは、ES6(ECMAScript 2015)で導入された組み込みオブジェクトの一つで、「キー」と「値」のペアで構成される要素を管理するコレクションです。通常のオブジェクトとよく似ていますが、Mapの大きな特徴は、キーにオブジェクトやプリミティブ値など、あらゆる型の値を使用できる点にあります。さらに、要素は挿入した順序で保持されるため、for...ofループなどを利用して、追加した順番どおりに反復処理を行うことも可能です。Mapオブジェクトの主なメソッドとプロパティメソッド / プロパティ説明new Map(iterable)配列などのイテラブル