Setに加わった「集合論的」なメソッド(1)
ES2025でNew Set methodsが標準化されてからは、Setの位置付けが変化しました。ただの「重複のないコレクション」が「集合論的」なメソッドを備えたデータ構造へと変化したのです。New Set methodsによって追加されたメソッドは以下の通りです(すべてSet.prototype配下)。
| メソッド | 概要 |
|---|---|
| intersection(other) | otherとの交差を得る |
| union(other) | otherとの和集合を得る |
| difference(other) | otherとの差を得る |
| symmetricDifference(other) | otherとの対称差を得る |
| isSubsetOf(other) | otherの部分集合であればtrueを返す |
| isSupersetOf(other) | otherが部分集合であればtrueを返す |
| isDisjointFrom(other) | otherと互いに素であればtrueを返す |
このうちintersection、union、difference、symmetricDifferenceの4つのメソッドは、2の集合の間で演算を行い、結果の集合を返します。これらのメソッドが実行する演算と結果は、以下の図の通りです。
isSubsetOf、isSupersetOf、isDisjointFromの3つのメソッドは、2つの集合の関係を判定して結果を論理値で返します。これらのメソッドが行う判定と結果は、以下の図の通りです。
なお部分集合には、完全一致を除く真部分集合という概念もありますが、ECMAScriptでは同一のものとして扱われます。
以降、それぞれのメソッドの動きをサンプルを通じて見ていきましょう。
2つの集合の交差を得る──intersectionメソッド
intersectionメソッドは、2つの集合の交差(A ∩ B)を計算して新たなSetオブジェクトを返します。交差とは、双方の集合に共通する要素を言います。論理演算で言えば論理積(AND)に相当するものと考えれば分かりやすいですね。
たとえば、数学が好きな生徒のリスト、理科が好きな生徒のリストがあるとき、数学と理科の両方が好きな生徒の数を求める、といった場合に利用できます。
以下のリストは、2つの集合の交差を求めるものですが、intersectionメソッドが使えないときの従来の方法、そしてintersectionメソッドによる方法の2つを示しています(出力例は同じなのでどちらか一方のみ掲載。以降も同様)。
const mathematics = new Set(['鈴木', '山田', '田中', '佐藤', '高橋']);
const science = new Set(['佐藤', '高橋', '伊藤', '渡辺', '山本']);
const intersection = new Set([...mathematics]
.filter(x => science.has(x))); // scienceにもある人を抽出
console.log(`数学も理科も好きな生徒は ${intersection.size} 人です。`);
console.log(`数学も理科も好きな生徒は ${mathematics.intersection(science).size} 人です。`); // 数学も理科も好きな生徒は 2 人です。
このように同じ結果が得られますが、intersectionメソッドを使わないと、既述のようにいったん配列に展開した上でfilterメソッドによって共通要素を抽出し、再びSetオブジェクトに戻すなどやや煩雑な処理となります。
2つの集合の和集合を得る――unionメソッド
unionメソッドは、2つの集合の和集合(A ∪ B)を計算して新たなSetオブジェクトを返します。和集合とは、文字通り双方の集合を合わせたものです。論理演算でいえば論理和(OR)に相当します。
たとえば、数学が好きな生徒のリスト、理科が好きな生徒のリストがあるとき、数学と理科のいずれかが好きな生徒の数を求める、といったときに利用できます。
以下のリストは、2つの集合の和集合を求めるものです。
const mathematics = new Set(['鈴木', '山田', '田中', '佐藤', '高橋']);
const science = new Set(['佐藤', '高橋', '伊藤', '渡辺', '山本']);
const union = new Set([...mathematics, ...science]);
console.log(`数学と理科のいずれかが好きな生徒は ${union.size} 人です。`);
console.log(`数学と理科のいずれかが好きな生徒は ${mathematics.union(science).size} 人です。`); // 数学と理科のいずれかが好きな生徒は 8 人です。
unionメソッドを使わずに和集合を求める方法として、2つの集合を配列に展開し、その配列からSetオブジェクトを生成しています。このとき、重複する要素があれば除去されるので、重複する要素を持てないというSetオブジェクトのルールは守られます。
2つの集合の差を得る――differenceメソッド
differenceメソッドは、2つの集合の差(A - B)を計算して新たなSetオブジェクトを返します。差は交差とは異なり、ある集合から見て別の集合にない要素を指します。たとえば、会員リストから退会者を除いたリストを作る、タスクリストから完了タスクを除いたリストを作る、といったときに利用できます。
以下のリストは、2つの集合の差を求めるものです。
const members = new Set(['鈴木', '山田', '田中', '佐藤', '高橋']);
const retired = new Set(['山田', '高橋']);
const difference = new Set([...members]
.filter(x => !retired.has(x))); // retiredにいない人だけを抽出
console.log(`退会者以外のメンバーは ${[...difference].join(', ')} です。`);
console.log(`退会者以外のメンバーは ${[...members.difference(retired)].join(', ')} です。`); // 退会者以外のメンバーは 鈴木, 田中, 佐藤 です。
この例ではdifferenceメソッドの結果を配列に展開して、joinメソッドで文字列化しています。Setオブジェクトには文字列化のメソッドはないので、このように配列を経由する必要があるのは変わりません。
