JavaScriptで配列をグループ化し、ユニークなユーザー数をカウントして新しい配列を作成する方法
JavaScriptでオブジェクトの配列を扱う際、特定のプロパティを基準にデータをグループ化し、それぞれのグループ内のユニークな要素をカウントしたい場面はよくあります。本記事では、そのような処理を実現する関数の実装方法を解説します。
問題の概要
まず、次のようなオブジェクトの配列があると仮定しましょう。
const arr = [
{ region: "Africa", fruit: "Orange", user: "Gary" },
{ region: "Africa", fruit: "Apple", user: "Steve" },
{ region: "Europe", fruit: "Orange", user: "John" },
{ region: "Europe", fruit: "Apple", user: "bob" },
{ region: "Asia", fruit: "Orange", user: "Ian" },
{ region: "Asia", fruit: "Apple", user: "Angelo" },
{ region: "Africa", fruit: "Orange", user: "Gary" }
];この配列に対して、「region(地域)」プロパティを基準にデータをグループ化した新しいオブジェクトの配列を作成するJavaScript関数が必要です。
さらに、各地域ごとのユニークなユーザー数もカウントする必要があります。つまり、同じ地域内で同じユーザーが複数回出現した場合は、1人として数えるという要件です。
期待される出力
上記の配列の場合、出力は次のようになります。なお、最後の「Gary」はアフリカ地域に重複しているため、Africa のカウントには含まれません。
const output = [
{
"region": "Africa",
"count": 2
},
{
"region": "Europe",
"count": 2
},
{
"region": "Asia",
"count": 2
}
];実装コード
この問題を解くコードは以下の通りです。
const arr = [
{ region: "Africa", fruit: "Orange", user: "Gary" },
{ region: "Africa", fruit: "Apple", user: "Steve" },
{ region: "Europe", fruit: "Orange", user: "John" },
{ region: "Europe", fruit: "Apple", user: "bob" },
{ region: "Asia", fruit: "Orange", user: "Ian" },
{ region: "Asia", fruit: "Apple", user: "Angelo" },
{ region: "Africa", fruit: "Orange", user: "Gary" }
];
const groupByArea = (arr = []) => {
const res = [];
arr.forEach(el => {
let key = [el.region, el.user].join('|');
if (!this[el.region]) {
this[el.region] = { region: el.region, count: 0 };
res.push(this[el.region]);
};
if (!this[key]) {
this[key] = true;
this[el.region].count++;
};
}, Object.create(null));
return res;
}
console.log(groupByArea(arr));コードの解説
この実装のポイントを順番に見ていきましょう。
1. ユニークキーの生成: [el.region, el.user].join('|') によって、地域とユーザーの組み合わせから一意なキー(例:Africa|Gary)を生成しています。これにより、同じユーザーが同じ地域で重複してカウントされるのを防ぎます。
2. グループの初期化: this[el.region] が存在しない場合、つまりその地域がまだ処理されていない場合は、{ region, count: 0 } 形式の新しいエントリを作成し、結果配列 res に追加します。
3. カウントの更新: 地域とユーザーの組み合わせキーが未登録の場合のみ、count をインクリメントします。これにより、ユニークなユーザーだけが正確に数えられます。
4. プロトタイプ汚染の防止: Object.create(null) を第2引数として渡すことで、this がプロトタイプチェーンを持たないプレーンなオブジェクトになるようにしています。これは、toString などの組み込みプロパティとの衝突を避けるための安全策です。
実行結果
コンソールに出力される結果は以下の通りです。
[
{ region: 'Africa', count: 2 },
{ region: 'Europe', count: 2 },
{ region: 'Asia', count: 2 }
]各地域に2人のユニークなユーザーが存在するため、すべての地域で count: 2 となっています。重複した「Gary」のレコードは正しく除外されていることが確認できます。
まとめ
このように、forEach とハッシュマップ的なオブジェクトを組み合わせることで、配列のグループ化とユニークカウントを効率的に実装できます。データ量が多い場合は、Map オブジェクトや reduce メソッドを使った代替実装も検討するとよいでしょう。
-
JavaScriptでnewキーワードを使って配列を作成する方法
JavaScriptでは、newキーワードとArray()コンストラクタを使用することで、簡単に配列を作成できます。本記事では、実際に動作するサンプルコードとともに、その基本的な使い方を解説します。 サンプルコード 以下は、newキーワードを使用してJavaScriptの配列を作成するコード例です。 <!DOCTYPE html> <html lang=ja> <head> <meta charset=UTF-8 /> <meta name=viewport content=width=device-width, initial-sca
-
JavaScriptでオブジェクトを新しい配列に変換する方法
JavaScriptでは、オブジェクトのプロパティやネストされたデータを取り出し、扱いやすい形で新しい配列にフォーマットできます。本記事では、学校(school)オブジェクトに含まれる生徒情報を、文字列形式の配列へ変換する実践的なコード例を紹介します。 ポイントとなるテクニック このサンプルでは、以下の2つのJavaScript機能を活用しています。 分割代入(Destructuring assignment):オブジェクトから特定のプロパティを簡潔に取り出す構文です。 for...of ループ:配列内の各要素を順番に処理するために使用します。 コード例 <!DOCTYPE html