SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

JavaScriptの「今」はこうなっている!現場のコードを変える注目機能を総ざらい

ECMAScriptのSetは単なる箱にあらず。使いどころを実践パターンとともに紹介

JavaScriptの「今」はこうなっている!現場のコードを変える注目機能を総ざらい 第4回

Setに加わった「集合論的」なメソッド(2)

2つの集合の対称差を得る――symmetricDifferenceメソッド

 symmetricDifferenceメソッドは、2つの集合の対称差(A △ B)を計算して新たなSetオブジェクトを返します。対称差とは、2つの集合のどちらか片方にしか存在しない要素です。2つの名簿を比べてどちらか一方にしか乗っていない人のリストを作ったり、変更前と変更後の差分リストを作る、といったときに利用できます。

 以下のリストは、2つの集合の対称差を求めるものです。

リスト symmetric_difference.js
const gym = new Set(['鈴木', '山田', '田中', '佐藤', '高橋']);
const pool = new Set(['伊藤', '渡辺', '山本', '田中', '佐藤']);

const symmetricDifference = new Set([...gym]
  .filter(x => !pool.has(x))		// gymからpoolにないものを抽出
  .concat([...pool]			// その結果にpoolを追加
  .filter(x => !gym.has(x))));		// その結果からgymにないものを抽出
console.log(`ジムかプールのどちらかにしか所属していない生徒は ${symmetricDifference.size} 名です。`);
console.log(`ジムかプールのどちらかにしか所属していない生徒は ${gym.symmetricDifference(pool).size} 名です。`);
	// ジムかプールのどちらかにしか所属していない生徒は 6 名です。

 symmetricDifferenceメソッドを使わない場合、filterメソッドを2回、concatメソッドを1回呼び出す必要があり、見た目に煩雑ですし、処理時間もかかります。symmetricDifferenceメソッドを使えば行おうとしていることが一目瞭然です。

部分集合であるか判定する――isSubsetOfメソッド

 ここからは、判定メソッドを紹介します。isSubsetOfメソッドは、集合Aが集合Bの部分集合(A ⊆ B)であるかを判定して、結果を論理値で返します。部分集合とは、集合Aの要素すべてを集合Bが含むという関係です。たとえば、ユーザーが持つ権限が必要権限を満たしているか確認するときなどに利用できます。

 以下のリストは、2つの集合がお互いに部分集合関係にあるかを調べるものです。

リスト is_subset_of.js
const required = new Set(["read", "write"]);
const user1 = new Set(["read", "write", "delete"]);
const user2 = new Set(["read"]);

const isSubsetOfMethod = (subSet, superSet) => [...subSet]
  .every((value) => superSet.has(value));	// すべてがsuperSetにあるか確認
console.log(`ユーザー1は権限を満たして${isSubsetOfMethod(required, user1)? 'います。':'いません。'}`);
// ユーザー1は権限を満たしています。
console.log(`ユーザー2は権限を満たして${isSubsetOfMethod(required, user2)? 'います。':'いません。'}`);
// ユーザー2は権限を満たしていません。
console.log(`ユーザー1は権限を満たして${required.isSubsetOf(user1)? 'います。':'いません。'}`);
// ユーザー1は権限を満たしています。
console.log(`ユーザー2は権限を満たして${required.isSubsetOf(user2)? 'います。':'いません。'}`);
// ユーザー2は権限を満たしていません。

 ここでは、isSubsetOfメソッドを使わない例として、isSubsetOfMethod関数を定義しました。この関数は、2つのSetオブジェクトを受け取り、一方の全要素に対してそれがもう一方に存在するかをeveryメソッドで判定しています。成立すれば、部分集合と見なせるわけです。

上位集合であるか判定する――isSupersetOfメソッド

 isSupersetOfメソッドはisSubsetOfメソッドの逆で、集合Aが集合Bの上位集合(A ⊇ B)であるかを判定して、結果を論理値で返します。上位集合とは、集合Aが集合Bの要素すべてを含むという関係です。

 位置付け的には、isSubsetOfメソッドのインスタンスと引数を逆にしたものです。よって、同様の目的で利用できます。

 以下のリストは、2つの集合がお互いに上位集合関係にあるかを調べるものです。

リスト is_superset_of.js
const required = new Set(["read", "write"]);
const user1 = new Set(["read", "write", "delete"]);
const user2 = new Set(["read"]);

const isSupersetOfMethod = (superSet, subSet) => [...subSet]
  .every((value) => superSet.has(value));	// すべてがsuperSetにあるか確認
console.log(`ユーザー1は権限を満たして${isSupersetOfMethod(user1, required)? 'います。':'いません。'}`);
// ユーザー1は権限を満たしています。
console.log(`ユーザー2は権限を満たして${isSupersetOfMethod(user2, required)? 'います。':'いません。'}`);
// ユーザー2は権限を満たしていません。
console.log(`ユーザー1は権限を満たして${user1.isSupersetOf(required)? 'います。':'いません。'}`);
// ユーザー1は権限を満たしています。
console.log(`ユーザー2は権限を満たして${user2.isSupersetOf(required)? 'います。':'いません。'}`);
// ユーザー2は権限を満たしていません。

 この通り、使い方はisSupersetOfメソッドと逆になります。また、ここでもisSupersetOfメソッドを使わない例としてisSupersetOfMethod関数を定義しました。行っていることは前項と変わらず、判定する集合を逆にしているだけです。

2つの集合が互いに素であるか判定する――isDisjointFromメソッド

 最後のisDisjointFromメソッドは、2つの集合AとBが互いに素(A ⊥ B)であるかを判定して、結果を論理値で返します。互いに素であるとは、2つの集合が共通の要素を持たないことを意味します。たとえば、ユーザーのロールが競合しないことを確認するときなどに利用できます。

 以下のリストは、3つの集合が互いに素であるかを調べるものです。

リスト is_disjoint_from.js
const adminRoles = new Set(["admin"]);
const bannedRoles = new Set(["banned"]);
const userRoles = new Set(["user", "banned"]);

const isDisjointFromMethod = (setA, setB) => [...setA]
  .every((value) => !setB.has(value));	// すべてがsetBにないか調べる
console.log(`adminとbannedは競合${isDisjointFromMethod(adminRoles, bannedRoles)? 'していません。':'しています。'}`);
// adminとbannedは競合していません。
console.log(`adminとuserは競合${isDisjointFromMethod(adminRoles, userRoles)? 'していません。':'しています。'}`);
// adminとuserは競合していません。
console.log(`userとbannedは競合${isDisjointFromMethod(userRoles, bannedRoles)? 'していません。':'しています。'}`);
// userとbannedは競合しています。

console.log(`adminとbannedは競合${adminRoles.isDisjointFrom(bannedRoles)? 'していません。':'しています。'}`);
console.log(`adminとuserは競合${adminRoles.isDisjointFrom(userRoles)? 'していません。':'しています。'}`);
console.log(`userとbannedは競合${userRoles.isDisjointFrom(bannedRoles)? 'していません。':'しています。'}`);
// 出力は同じ

まとめ

 今回は、ECMAScript 2025で導入されたNew Set methodsを紹介しました。ただの重複のないコレクションであったSetが、本来の役割としての集合論的な機能を持つオブジェクトに変化したことをお伝えすることができたのではないかと思います。

 次回からは、ECMAScriptで最近標準化された有用な機能をいくつかピックアップし、紹介していきます。

この記事は参考になりましたか?

連載通知を行うには会員登録(無料)が必要です。
既に会員の方はを行ってください。
JavaScriptの「今」はこうなっている!現場のコードを変える注目機能を総ざらい連載記事一覧

もっと読む

この記事の著者

WINGSプロジェクト 山内 直(WINGSプロジェクト ヤマウチ ナオ)

<WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。 2026年時点での登録メンバは約50名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書、記事多数。 RSS X: @WingsPro_info(公式)、@WingsPro_info/wings(メンバーリスト) Facebook <個人紹介>WINGSプロジェクト所属のテクニカルライター。出版社を経てフリーランスとして独立。ライター、エディター、デベロッパー、講師業に従事。屋号は「たまデジ。」。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるLaravel実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/29909 2026/10/14 09:00

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー