【STEP.24】
セット(Set)の使い方をマスターしよう!

Setオブジェクトとは

Setオブジェクトは、重複しない値の集合を管理するためのオブジェクトです。

重複した値が追加された場合には、これを無視します。

SetはES2015から新たに導入されたオブジェクトで、それ以前のJavaScriptでは、直接の代替となる手段は用意されていません。

Setオブジェクトのメンバー一覧

Setオブジェクトで利用可能なメンバーは、以下の通りです。

【Setオブジェクトの主なメンバー】
メンバー概要
size要素数
add(val)指定した値を追加
has(val)指定した値が存在するかを判定
delete(val)指定した値の要素を削除
clear()すべての要素を削除
entries()すべてのキー/値を取得
values()すべての値を取得(エイリアスとしてkeysメソッドも利用可能)
forEach(fnc [,that])指定した関数をSetの各値ごとに処理

参照型とNaNの扱い

参照型、NaNの比較ルールは、マップのそれと同じです。

そのため、NaNを複数追加した場合には同じものと見なされ無視されますし、たとえば空のオブジェクトを2個追加した場合は、互いに参照としては別物なので、それぞれに追加されます。

let s1 = new Set([NaN,NaN]);
let s2 = new Set([{},{}]);

console.log(s1.size);
//結果:1(同じ値は無視されます。)
console.log(s2.size);
//結果:2(それぞれ異なるオブジェクトとして追加されます。)

sizeプロパティはセット内の要素数を返します。

キーを弱参照で管理する【WeakSet/WeakMapオブジェクト】

SetMapにはよく似たオブジェクトとして、WeakSetWeakMapと呼ばれる、キーを弱参照で管理するオブジェクトがあります。

弱参照とは、このマップ以外でキーが参照されなくなると、そのままガベージコレクトの対象になる(=破棄される)ということです。

標準のMapSetでは、いわゆる強参照でキーを管理するので、マップ/セットでキーを保持している限り、キーオブジェクトは破棄の対象にはなりません。

その性質上、WeakMapWeakSetでは、

  • キーは参照型でなければならない
  • 列挙できない(必要であれば、自分で管理)

などの制約があります。

セットを作成する【Setコンストラクター】

Setを作成するには次のSetコンストラクター構文を利用します。

Setコンストラクター

new Set([value,...])
value    値

セットに設定すべき値を配列として渡します。

もともとの配列に重複があった場合には、重複は除去されます。

let s = new Set(['ド','ミ','ソ','ド']);

console.log(s);
//結果:{"ド", "ミ", "ソ"}

セットに値を追加する【add】

addメソッドを利用します。

addメソッド

set.add(value)
value    値

重複した値を追加した場合、addメソッドはこれを無視します。

let s = new Set();
	
s.add('ド');
s.add('ミ');
s.add('ソ');
s.add('ド');//重複は無視されます
console.log(s);
//結果:{"ド", "ミ", "ソ"}

addメソッドは、戻り値としてSetオブジェクト自身を返すので、以下のように「.」演算子を連ねて表すこともできます。(このような書き方をメソッドチェーンといいます。)

let s = new Set();
	
s.add('ド').add('ミ').add('ソ').add('ド');
console.log(s);
//結果:{"ド", "ミ", "ソ"}

セットに値が存在するかを判定する【has】

セットは、配列/マップと異なり、インデックス番号/キーなどで個々の要素にアクセスする手段を持ちません。

セットでできるのは、for…ofループ、またはforEachメソッドで列挙するか、hasメソッドで値の存在を確認するだけです。

hasメソッド

set.has(value)
value    値

セットに値が存在する場合、hasメソッドはtrueを、さもなくばfalseを返します。

let s = new Set();
	
s.add('ド');
s.add('ミ');
s.add('ソ');
	
console.log(s.has('ド'));
//結果:true
console.log(s.has('レ'));
//結果:false

セットからすべての値を取り出す【forEach】

forEachメソッドを利用します。

forEachメソッド

set.forEach(function(value, value2, set) {
  ...statements...
}, that)
value, value2  要素値
set            元のセット
statements     要素に対する処理
that           thisが表す値

コールバック関数はいずれも省略可能です。

たとえば以下は、セットの内容を順番に取り出し、ログに出力する例です。

let s = new Set();
	
s.add('ド');
s.add('ミ');
s.add('ソ');
	
s.forEach(function (value) {
  console.log(value);
  //結果:ド、ミ、ソ
});

以下のようにfor…ofループを利用することもできます。

let s = new Set();
	
s.add('ド');
s.add('ミ');
s.add('ソ');
	
for (let value of s) {
  console.log(value);
  //結果:ド、ミ、ソ
}	

for(let value of s)」の部分は「for(let value of s.values())」としても、ほぼ同じ意味です。

valuesメソッドは、セット内の値を配列として返します。

セットから既存の値を削除する【delete】

セットから特定の値を削除するには、deleteメソッドを利用します。

deleteメソッド

set.delete(value)
value    削除する値

deleteメソッドは、キーを削除できたらtrueを返します。(キーが存在しない場合などで削除できなかった場合はfalseを返します。)

let s = new Set();
	
s.add('ド');
s.add('ミ');
s.add('ソ');
	
console.log(s.delete('ド'));
//結果:true
console.log(s.delete('レ'));
//結果:false

特定の値ではなくすべてのキーを削除したい場合には、clearメソッドを利用します。

s.clear();

配列から重複を除去する【Setオブジェクト/スプレッド演算子】

Set、スプレッド演算子を組み合わせることで、配列に含まれている重複した要素を除去できます。

let data = ['あ','え','い','い','あ','う'];

let unique = [...(new Set(data))];
	
console.log(unique);
	
//結果:["あ", "え", "い", "う"]

配列をSetコンストラクターに渡すことで重複を除去し、スプレッド演算子で再び配列に変換しています。


コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です