Levix

Levix's zone

x
telegram

JavaScript Sets は、まもなく和集合、積集合、差集合などのより多くの操作をサポートします。

JavaScript Set は ES2015 規格で導入されて以来、機能が不十分と見なされてきました。しかし、今、その状況は変わろうとしています。

Sets は値が一意で重複しないことを保証する集合型です。ES2015 バージョンでは、Set が提供する機能は主に要素の作成、追加、削除、および要素が特定の Set に属しているかどうかの確認に限られています。複数の集合を操作または比較する必要がある場合は、自分で関数を作成する必要があります。幸いなことに、ECMAScript 規格の策定委員会 TC39 と主要なブラウザ開発者はこの点で進展を遂げています。現在、JavaScript では union(和集合)、intersection(共通集合)、および difference(差集合)などの操作が利用できるようになりました。

これらの新機能を深く理解する前に、まず既存の JavaScript Sets が何をできるかを振り返り、その後に以下の 新 Set 関数これらの機能をサポートする JavaScript エンジン について探ってみましょう。

ES2015 バージョンの JavaScript Sets でできる操作は?#

いくつかの例を通じて JavaScript Set の基本機能を探るのが最も直接的な方法です。

空の Set を作成することも、イテラブルオブジェクト(配列など)を提供して Set を初期化することもできます。

const languages = new Set(["JavaScript", "TypeScript", "HTML", "JavaScript"]);

Set の値は一意でなければならないため、上記の Set には実際には三つの要素が含まれています。これを確認するには、Setsize プロパティを使用します。

languages.size;

// => 3

add メソッドを使用して新しい要素を Set に追加できます。追加しようとした要素がすでに存在する場合、何も変化はありません。

languages.add("JavaScript");

languages.add("CSS");

languages.size;

// => 4

delete メソッドを使用して Set から要素を削除できます。

languages.delete("TypeScript");

languages.size;

// => 3

has メソッドを使用して、特定の要素が Set に属しているかどうかを確認できます。配列と比較して、Set のこの確認は効率が高く、操作の時間計算量は定数時間(O(1))です。

languages.has("JavaScript");

// => true

languages.has("TypeScript");

// => false

forEach または for...of ループを使用して Set の要素を反復処理することもできます。要素の順序は、Set に追加された順序に従います。

languages.forEach(element => console.log(element));

// "JavaScript"

// "HTML"

// "CSS"

さらに、keysvalues(実際には keys と同等)および entries メソッドを使用して Set からイテレータを取得できます。

最後に、clear メソッドを使用して Set を空にすることができます。

languages.clear();

languages.size;

// => 0

これは、ES2015 規格の Set で実行可能な操作の簡単な振り返りです:

  • Set は一意の値の集合を扱うためのメソッドを提供します。
  • Set に要素を追加したり、要素が Set に存在するかどうかをテストするのは非常に効率的です。
  • Array または他のイテラブルオブジェクトを Set に変換することは、重複を排除する簡単な方法です。

しかし、この実装は Set 同士の操作能力が欠けています。二つの Set を結合して両方のすべての要素を含む新しい Set(和集合)を作成したり、二つの Set の共通要素(共通集合)を見つけたり、一方の Set にあり他方の Set にない要素(差集合)を特定したりすることを望むかもしれません。最近まで、これらの操作を実現するにはカスタム関数が必要でした。

新しい Set 関数には何が含まれていますか?#

Set メソッドの提案は、Set インスタンスに以下のメソッドを追加します:union(和集合)、intersection(共通集合)、difference(差集合)、symmetricDifference(対称差集合)、isSubsetOf(部分集合の判断)、isSupersetOf(超集合の判断)、および isDisjointFrom(相互に交差しないかの判断)。

これらのメソッドのいくつかは SQL の特定の結合操作に似ており、各関数の動作をコード例を通じて示します。

以下のコード例は、Chrome 122+ または Safari 17+ で試すことができます。

Set.prototype.union(other)#

二つの集合の和集合は、二つの集合のすべての要素を含む集合です。

const frontEndLanguages = new Set(["JavaScript", "HTML", "CSS"]);

const backEndLanguages = new Set(["Python", "Java", "JavaScript"]);

const allLanguages = frontEndLanguages.union(backEndLanguages);

// => Set {"JavaScript", "HTML", "CSS", "Python", "Java"}

この例では、最初の集合と二番目の集合のすべての言語が三番目の集合に含まれています。他の方法で Set に要素を追加するのと同様に、重複する要素は自動的に排除されます。

これは二つのテーブルに対して SQL の FULL OUTER JOIN を実行するのと同等です。

和集合のベン図、二つの集合のすべての内容が選択されていることを示しています。

Set.prototype.intersection(other)#

二つの集合の共通集合は、二つの集合に共通する要素を含む集合です。

const frontEndLanguages = new Set(["JavaScript", "HTML", "CSS"]);

const backEndLanguages = new Set(["Python", "Java", "JavaScript"]);

const frontAndBackEnd = frontEndLanguages.intersection(backEndLanguages);

// => Set {"JavaScript"}

ここで、「JavaScript」は二つの集合に同時に出現する唯一の要素です。

共通集合は SQL の INNER JOIN に相当します。

二つの集合の共通集合を示すベン図。二つの集合に共通する項目のみが選択されています。

Set.prototype.difference(other)#

操作する集合と別の集合との間の差集合は、最初の集合に特有のすべての要素を含みます。

const frontEndLanguages = new Set(["JavaScript", "HTML", "CSS"]);

const backEndLanguages = new Set(["Python", "Java", "JavaScript"]);

const onlyFrontEnd = frontEndLanguages.difference(backEndLanguages);

// => Set {"HTML", "CSS"}

const onlyBackEnd = backEndLanguages.difference(frontEndLanguages);

// => Set {"Python", "Java"}

二つの集合間の差異を特定する際には、差集合関数を呼び出す集合と引数として渡す集合の順序が非常に重要です。上記の例では、フロントエンド言語の集合からバックエンド言語の集合を除外した結果、「JavaScript」が削除され、「HTML」と「CSS」が残ります。逆に、バックエンド言語の集合からフロントエンド言語の集合を除外しても「JavaScript」が削除され、「Python」と「Java」が残ります。

差集合は SQL の LEFT JOIN を実行するのに似ています。

二つの集合の差異を示すベン図、最初の集合に特有の項目のみが選択されています。

Set.prototype.symmetricDifference(other)#

二つの集合の対称差集合は、二つの集合に特有のすべての要素を含む集合です。

const frontEndLanguages = new Set(["JavaScript", "HTML", "CSS"]);

const backEndLanguages = new Set(["Python", "Java", "JavaScript"]);

const onlyFrontEnd = frontEndLanguages.symmetricDifference(backEndLanguages);

// => Set {"HTML", "CSS", "Python", "Java"}

const onlyBackEnd = backEndLanguages.symmetricDifference(frontEndLanguages);

// => Set {"Python", "Java", "HTML", "CSS"}

この場合、結果集合の要素は同じですが、要素の順序は呼び出された集合によって異なります。要素の追加順序は、それらが集合に追加された順序によって決まり、関数を操作する集合の要素が最初に追加されます。

対称差集合は SQL で二つのテーブルの共通要素を除外する FULL OUTER JOIN に似ています。

対称差集合のベン図、二つの集合に特有のすべての内容が選択されています。

Set.prototype.isSubsetOf(other)#

最初の集合のすべての要素が二番目の集合に存在する場合、その集合は別の集合の部分集合です。

const frontEndLanguages = new Set(["JavaScript", "HTML", "CSS"]);

const declarativeLanguages = new Set(["HTML", "CSS"]);

declarativeLanguages.isSubsetOf(frontEndLanguages);

// => true

frontEndLanguages.isSubsetOf(declarativeLanguages);

// => false

任意の集合は自分自身の部分集合です。

frontEndLanguages.isSubsetOf(frontEndLanguages);

// => true

Set.prototype.isSupersetOf(other)#

最初の集合が二番目の集合のすべての要素を含む場合、その集合は別の集合の超集合です。これは部分集合の逆の関係です。

const frontEndLanguages = new Set(["JavaScript", "HTML", "CSS"]);

const declarativeLanguages = new Set(["HTML", "CSS"]);

declarativeLanguages.isSupersetOf(frontEndLanguages);

// => false

frontEndLanguages.isSupersetOf(declarativeLanguages);

// => true

任意の集合は自分自身の超集合です。

frontEndLanguages.isSupersetOf(frontEndLanguages);

// => true

Set.prototype.isDisjointFrom(other)#

二つの集合に共通の要素がない場合、それらは交差しません。

const frontEndLanguages = new Set(["JavaScript", "HTML", "CSS"]);

const interpretedLanguages = new Set(["JavaScript", "Ruby", "Python"]);

const compiledLanguages = new Set(["Java", "C++", "TypeScript"]);

interpretedLanguages.isDisjointFrom(compiledLanguages);

// => true

frontEndLanguages.isDisjointFrom(interpretedLanguages);

// => false

これらの例では、解釈型言語とコンパイル型言語の集合には交差がないため、これらの集合は交差しません。一方、フロントエンド言語と解釈型言語の集合は「JavaScript」という共通の要素があるため、交差しないわけではありません。

サポート状況#

この記事執筆時点で、これらの新しい Set メソッドの 提案 は TC39 の標準化プロセスの第 3 段階に入り、Safari 17(2023 年 9 月リリース)および Chrome 122(2024 年 2 月)でこれらのメソッドが実装されました。Edge は Chrome に続いてリリースされ、Firefox Nightly は実験的なフラグの後にこれらの機能をサポートしており、これらのブラウザもすぐに正式にサポートされる見込みです。

Bun もまた Safari の JavaScriptCore エンジンを採用しているため、これらの新機能をサポートしています。Chrome のこれらの機能のサポートは、これらが V8 JavaScript エンジンに統合され、近く Node.js にも採用されることを意味します。

これが、これらの提案がプロセスの第 4 段階にスムーズに移行し、タイムリーに ES2024 規格の一部となることを期待しています。

ポリフィル#

古い JavaScript エンジンでこれらの機能をサポートする必要がある場合は、ポリフィルを使用できます。これらのポリフィルは core-js から入手できるか、es-shims プロジェクトの個別パッケージとして提供されています(例えば、和集合機能を実装するための set.prototype.union パッケージ)。

これらの機能のために独自の実装を作成している場合は、まずこれらのポリフィルに移行し、これらの機能が広くサポートされるにつれて、カスタム実装を段階的に廃止することをお勧めします。

Sets の機能が欠けているとは感じなくなった#

JavaScript Set は長い間機能が不完全と見なされてきましたが、これらの七つの新しい関数の追加により、その機能はより充実しました。このような機能が言語自体に組み込まれることは、外部依存や独自実装の必要性を減らし、実際の問題解決により集中できることを意味します。

これは TC39 が現在審議している多くの第 3 段階提案の一部に過ぎません。このリストを確認して、JavaScript に今後追加される可能性のある新機能を把握してください。特に TemporalDecorators に注目しており、これらの提案は私たちが JavaScript を記述する重要な部分の方法を変える可能性があります。

原文リンク

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。