公開日

JavaScript Set:初心者開発者向けの基礎

著者

なぜ Set を使うのか?

Set は、あらゆる型のユニークな値を格納できるデータ構造です。配列に似ていますが、重複した値を許容しません。あらゆる種類のユニークな値を保持するのに最適な方法です。

配列にユニークな値を格納したい場合がありますが、その値が既に存在するかどうかを調べるために配列全体をループ処理したくありません。このような場合に Set が役立ちます。

以前の記事では、Javascript Mapについて説明しました。Set は Map に似ていますが、値ではなくキーのみを格納します。これは、あらゆる型のユニークな値を保持するのに最適な方法です。多くの場合、Map を使用するのは大変です。そのため、Set について説明します。

JavaScript の Set とは?

Set オブジェクトは、値の集合です。Set 内の値は一度だけ出現します。つまり、Set の集合内ではユニークです。Set の要素は、挿入順に反復処理できます。挿入順序は、各要素が add() メソッドによって Set に正常に挿入された順序に対応します(つまり、Set が add() を呼び出したときに、既に同一の要素が Set に存在していませんでした)。

仕様では、Set は「コレクション内の要素の数に対して平均的にサブ線形なアクセス時間を提供する」ように実装する必要があります。したがって、内部的にはハッシュテーブル(O(1) のルックアップ)、探索木(O(log(N)) のルックアップ)、またはその他のデータ構造で表すことができます。重要なのは、複雑さが O(N) よりも優れていることです。

Set の作成方法

Set を作成するには、2 つの方法があります。1 つ目は、Set コンストラクターを使用する方法です。2 つ目は、Set オブジェクトリテラルを使用する方法です。

Set コンストラクター

Set コンストラクターは、新しい Set オブジェクトを作成します。コンストラクターには、反復可能なオブジェクトを引数として渡すことができます。反復可能なオブジェクトの要素は、新しい Set に追加されます。

const set = new Set([1, 2, 3, 4, 5]);

Set オブジェクトリテラル

Set オブジェクトリテラルは、新しい Set オブジェクトを作成します。オブジェクトリテラルには、反復可能なオブジェクトを引数として渡すことができます。反復可能なオブジェクトの要素は、新しい Set に追加されます。

const set = {1, 2, 3, 4, 5};

Set のメソッドとプロパティ

メソッド説明
add()Set オブジェクトに指定された値を持つ新しい要素を追加します。
clear()Set オブジェクトからすべての要素を削除します。
delete()値に関連付けられている要素を削除し、Set.prototype.has(value) が以前返していた値を返します。Set.prototype.has(value) は、その後 false を返します。
entries()Set オブジェクトの各要素に対する [value, value] の配列を含む新しい Iterator オブジェクトを返します。挿入順で返されます。
forEach()Set オブジェクトの各値に対して、指定された関数を一度実行します。挿入順で実行されます。
has()Set オブジェクトに指定された値を持つ要素が存在するかどうかを示すブール値を返します。
keys()Set オブジェクトの各要素の値を含む新しい Iterator オブジェクトを返します。挿入順で返されます。
values()Set オブジェクトの各要素の値を含む新しい Iterator オブジェクトを返します。挿入順で返されます。
プロパティ説明
sizeSet オブジェクト内の値の数を返します。

Set の例

Set に値を追加する

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

Set から値を削除する

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

Set に値が存在するかどうかを確認する

const set = new Set([1, 2, 3, 4, 5]);
console.log(set.has(3)); // true

Set を反復処理する

const set = new Set([1, 2, 3, 4, 5]);
for (const item of Set) {
  console.log(item);
}
// 1
// 2
// 3
// 4
// 5

Set を配列に変換する

const set = new Set([1, 2, 3, 4, 5]);
const array = Array.from(set);
console.log(array); // [1, 2, 3, 4, 5]

配列を Set に変換する

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

Set のサイズを取得する

const set = new Set([1, 2, 3, 4, 5]);
console.log(set.size); // 5

Set をクリアする

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

Set をマージする

const set1 = new Set([1, 2, 3, 4, 5]);
const set2 = new Set([6, 7, 8, 9, 10]);
const set3 = new Set([...set1, ...set2]);
console.log(set3); // Set { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }

2 つの Set の共通部分を取得する

const set1 = new Set([1, 2, 3, 4, 5]);
const set2 = new Set([4, 5, 6, 7, 8]);
const set3 = new Set([...set1].filter((x) => set2.has(x)));
console.log(set3); // Set { 4, 5 }

2 つの Set の差分を取得する

const set1 = new Set([1, 2, 3, 4, 5]);
const set2 = new Set([4, 5, 6, 7, 8]);
const set3 = new Set([...set1].filter((x) => !set2.has(x)));
console.log(set3); // Set { 1, 2, 3 }

Set が別の Set の部分集合であるかどうかを確認する

const set1 = new Set([1, 2, 3, 4, 5]);
const set2 = new Set([4, 5]);
console.log([...set2].every((x) => set1.has(x))); // true

Set が別の Set の上位集合であるかどうかを確認する

const set1 = new Set([1, 2, 3, 4, 5]);
const set2 = new Set([4, 5]);
console.log([...set1].every((x) => set2.has(x))); // false

2 つの Set が互いに素であるかどうかを確認する

const set1 = new Set([1, 2, 3, 4, 5]);
const set2 = new Set([6, 7, 8, 9, 10]);
console.log([...set1].every((x) => !set2.has(x))); // true

2 つの Set が等しいかどうかを確認する

const set1 = new Set([1, 2, 3, 4, 5]);
const set2 = new Set([1, 2, 3, 4, 5]);
console.log(set1.size === set2.size && [...set1].every((x) => set2.has(x))); // true

ブラウザのサポート

ChromeChromeFirefoxFirefoxEdgeEdgeSafariSafariOperaOpera
49+44+12+10.1+36+

Set vs. Array

SetArray
ユニークな値で、重複値を許容しない重複値を許容する
Set は、特定の順序を持たない値の集合ですArray は、特定の順序を持つ値の集合です
Set は反復処理可能ですArray は反復処理可能です
Set は、ハッシュ処理を使用するため、配列よりも初期化が遅いです。Array は、初期化が高速です。
要素の存在を確認する場合のパフォーマンスが優れています。要素にアクセスする場合のパフォーマンスが優れています。

この記事は、blog.imam.dev に最初に公開されました。

参考文献

  1. Mozilla Developer Network - Set

  2. W3Schools - Set

  3. ECMAScript® 2015 Language Specification - Set