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

【JavaScript】同じキー値を持つオブジェクトをマージして出現回数をカウントする方法

データ処理を行っていると、「同じIDを持つ重複データを1つにまとめて、それぞれ何件ずつ存在するかを集計したい」というケースによく遭遇します。

この記事では、id プロパティの値が同じオブジェクトを1つにマージし、出現回数を count プロパティとして付与する方法を、reduce メソッドを使ったサンプルコードとともに解説します。

元となる配列

まず、次のようなオブジェクトの配列があると仮定しましょう。

const arr = [{
    "value": 10,
    "id": "111",
    "name": "BlackCat",
}, {
    "value": 10,
    "id": "111",
    "name": "BlackCat",
}, {
    "value": 15,
    "id": "777",
    "name": "WhiteCat",
}];

この配列には、id"111" のオブジェクトが2件、"777" のオブジェクトが1件含まれています。

要件

このような配列を引数として受け取り、id プロパティの値が同じオブジェクト同士をマージして、それぞれの出現回数をカウントするJavaScript関数を作成します。

上記の配列に対して実行した場合、期待される出力は以下のようになります。

const output = [{
    "value": 10,
    "id": "111",
    "name": "BlackCat",
    "count": 2,
}, {
    "value": 15,
    "id": "777",
    "name": "WhiteCat",
    "count": 1,
}]

実装コード例

reduce メソッドを使うことで、配列を走査しながら結果を蓄積できます。すでに同じ id の要素が存在する場合は count をインクリメントし、存在しない場合は新たな要素として追加します。

const arr = [{
    "value": 10,
    "id": "111",
    "name": "BlackCat",
}, {
    "value": 10,
    "id": "111",
    "name": "BlackCat",
}, {
    "value": 15,
    "id": "777",
    "name": "WhiteCat",
}];

const combinedItems = (arr = []) => {
    const res = arr.reduce((acc, obj) => {
        let found = false;
        for (let i = 0; i < acc.length; i++) {
            if (acc[i].id === obj.id) {
                found = true;
                acc[i].count++;
            };
        }
        if (!found) {
            obj.count = 1;
            acc.push(obj);
        }
        return acc;
    }, []);
    return res;
}

console.log(combinedItems(arr));

実行結果

コンソールに出力される結果は以下の通りです。id ごとにオブジェクトがまとめられ、count に出現回数が記録されていることが確認できます。

[
    { value: 10, id: '111', name: 'BlackCat', count: 2 },
    { value: 15, id: '777', name: 'WhiteCat', count: 1 }
]

補足:より効率的な書き方

上記のコードは毎回結果配列を線形探索するため、データ量が多い場合は計算量が O(n²) になります。パフォーマンスを重視する場合は、Map やオブジェクトをキー管理用に使うことで O(n) に改善できます。

const combinedItems = (arr = []) => {
    const map = new Map();
    arr.forEach(obj => {
        if (map.has(obj.id)) {
            map.get(obj.id).count++;
        } else {
            map.set(obj.id, { ...obj, count: 1 });
        }
    });
    return [...map.values()];
}
  1. 文字列キーを使ってネストされたJavaScriptオブジェクトに安全にアクセスする方法

    JavaScriptでネストされたオブジェクトのプロパティにアクセスする際、存在しないパスを指定するとエラーが発生する可能性があります。そんなときに便利なのが、lodashライブラリが提供する get メソッドです。このメソッドを使えば、任意の階層のプロパティを安全に取得できます。 第一階層のプロパティへのアクセスは比較的シンプルですが、深くネストされたプロパティへのアクセスは注意が必要です。独自の実装で対応するよりも、lodashのように十分にテストされたライブラリを活用するのがおすすめです。 lodashのgetメソッドを使ったアクセス方法 lodashの get メソッドを使用すると、以

  2. JavaScriptで配列の要素を同じ配列内に複製する方法

    JavaScriptでは、concat()メソッドとsort()メソッドを組み合わせることで、既存の配列の要素を同じ配列内に複製することができます。ここでは、実際に動作するサンプルコードを使って、その手順をわかりやすく解説します。 コード例 以下は、配列の要素を同じ配列内に複製するためのコード例です。 <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8" /> <meta name="viewport" cont