2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【JavaScript】Setで実現するデータ処理 重複排除と高速検索

Posted at

はじめに

JavaScriptにおいて、データの中から重複を取り除き、ユニークな値のみを管理する必要が生じる場面は少なくありません。例えば、ユーザーからの入力値の正規化、タグやカテゴリの一覧表示、ログデータの集計時などが挙げられます。
このような要件を満たすデータ構造として、組み込みオブジェクトである Set が提供されています。

この記事では、Set の基本的な操作方法からユ-スケース、注意点など実際のコード例を交えて記載します。

Set とは?

Set は 重複のない値の集合 を保持するための組み込みオブジェクトです。
値の順序は保持されますが、重複する値は自動的に排除されます。

.js
const set = new Set([1, 2, 3, 3, 2]);
console.log(set); // Set(3) { 1, 2, 3 }

上記のように、配列に重複があっても、Set に渡すとユニークな値だけが残ります。

基本的な操作方法

1. 値の追加・削除・存在確認

.js
const fruits = new Set();

fruits.add("apple");
fruits.add("banana");
fruits.add("apple"); // 重複は無視される

console.log(fruits); // Set(2) {'apple', 'banana'}
console.log(fruits.has("banana")); // true

fruits.delete("banana");
console.log(fruits.has("banana")); // false

2. イテレーション(ループ)

Setfor...offorEach でループ可能です。

.js
const colors = new Set(["red", "green", "blue"]);

for (const color of colors) {
  console.log(color);
}
// red
// green
// blue

Set が活躍する代表的なユースケース

1. 配列の重複を排除

🛠️ユースケース:チェックボックスで選ばれたカテゴリの送信前処理

チェックボックス形式でカテゴリを選択するフォームを作る場合、UIのバグやユーザー操作の繰り返しで、同じカテゴリが複数回選ばれてしまう可能性があります。
そのまま送信すると、APIに同じカテゴリIDが複数回送られてしまい、保存や集計の不具合につながることもあります。

Set を使えば簡単に重複を取り除いて送信できます。

.js
const selectedCategoryIds = [1, 3, 2, 3, 1];
const uniqueCategoryIds = [...new Set(selectedCategoryIds)];

console.log(uniqueCategoryIds);
// => [1, 3, 2]

// 例: fetch('/api/update', { method: 'POST', body: JSON.stringify({ categoryIds: uniqueCategoryIds }) })

💡Setを使って嬉しいポイント

  • 重複除去のロジックが1行で書けて可読性が高い
  • ユーザーの意図しない重複送信によるサーバーエラーを防止

2. 大量データに対する存在チェック

🛠️ユースケース:ログイン中ユーザーが過去に閲覧した記事かを高速に判定する

「すでに閲覧済みの記事にはチェックマークを表示する」ようなUIを実装する場合、過去に閲覧した記事IDを保持し、その中に現在表示している記事IDが含まれているかを繰り返しチェックする必要があります。

Array.includes() では閲覧履歴が数千件以上になるとパフォーマンスに影響することがありますが、Set.has() なら高速です。

.js
const viewedArticleIds = new Set([1001, 1002, 1003, 1004]);

const currentArticleId = 1002;

if (viewedArticleIds.has(currentArticleId)) {
  console.log("✔ 閲覧済みマークを表示");
} else {
  console.log("未閲覧");
}

💡Setを使って嬉しいポイント

  • 数千〜数万件のデータでも即時判定が可能
  • リアルタイムなUI更新やフィルタリング処理に適している
  • .has()O(1) なのでループの中でも安心して使える

O(1) とは?

データの量が増えても、処理にかかる時間がほとんど変わらないということです。

  • Array.includes() の場合(O(N) に近いイメージ)
    • 過去の閲覧履歴がどれだけ多くても、一つずつ順番に確認していく必要があります
    • 履歴が増えるほど、チェックにかかる時間も長くなります
  • Set.has() の場合(O(1) のイメージ)
    • 閲覧履歴がどれだけ多くても、目的の記事IDを「一瞬で」見つけられるようなものです
    • データの量が増えても、確認にかかる時間はほとんど変わりません

このように、Set.has() は非常に高速に目的のデータがあるかを確認できるため、数千〜数万件のデータでも即時判定が可能でループの中でも安心して利用できます。

3. 集合演算(和・積・差)によるデータ比較・統合

🛠️ユースケース:ユーザーの権限変更画面で、追加・削除すべきロールを計算する

管理画面でユーザーのロールを更新するとき、「すでに持っているロール」と「新たに指定されたロール」の差分を使って、追加すべきロールと削除すべきロールを求める必要があります。

Set を使うと、重複や順序を気にせず論理的な集合演算ができ、無駄なく効率的に差分を計算できます。

.js
  const currentRoles = new Set(["viewer", "editor"]);
  const updatedRoles = new Set(["admin", "editor"]);

  // 削除するロール(現在はあるが、更新後はない)
  const rolesToRemove = [...currentRoles].filter(
    (role) => !updatedRoles.has(role)
  );
  console.log(rolesToRemove);
  // => ["viewer"]

  // 追加するロール(更新後にはあるが、現在はない)
  const rolesToAdd = [...updatedRoles].filter(
    (role) => !currentRoles.has(role)
  );
  console.log(rolesToAdd);
  // => ["admin"]

💡Setを使って嬉しいポイント

  • 簡潔な記述で差分の検出処理が書ける
  • 並び順や重複を気にせず、論理的な一致だけに集中できる
  • 和集合・積集合などの応用処理も同じ構文で実装可能

注意点

1. オブジェクトや配列は「同じ内容」でも別物と判定される

オブジェクトや配列などの参照型は、内容が同じでも別物とみなされる ことに注意しましょう。

const set = new Set();
set.add({ name: "Alice" });
set.add({ name: "Alice" });

console.log(set.size); // 2(同じ内容でも別のオブジェクト)

2. 順序を保証したい場合は配列を併用

Set の順序は「追加順」ですが、ソートは自動では行われません。
順序を厳密に制御したい場合は、Array.from(set).sort() などで対応する必要があります。

.js
const scores = new Set([40, 10, 20]);
const sorted = [...scores].sort((a, b) => a - b);
console.log(sorted); // [10, 20, 40]

おわりに

JavaScript の Set は、配列処理や集合演算、重複排除において強力なツールです。
用途に応じて、MapArray と適切に使い分けられるようになると、コードの効率性や可読性が向上します。

参考

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?