【TC39 Proposals】New Set methods


注意書き

2019 年 10 月 9 日に開催の #tc39_study 用に作成した資料です。
執筆時点で TC39 の Proposals に上がっている機能を紹介します。
将来的に JavaScript(ECMAScript)に取り入れられるかもしれませんし、取り入れられないかもしれませんし、紹介内容から仕様が大きく変更になるかもしれません。
TC39 の承認プロセスについては、https://tc39.es/process-document/ をご覧ください。


New Set methods

現状の Set オブジェクトには、要素の追加・削除、要素が集合に含まれているかの基本的な操作しか提供されていません。
この Proposal は Set オブジェクトに集合操作のメソッドを追加するものです。
他の言語や Immutable.js などのライブラリで使われているものと同等の機能を標準に取り入れます。
執筆時点で Stage 2 です。


Set.prototype.intersection()

集合 $A$ と集合 $B$ の積集合 $A \cap B$ を返します。

使い方

const a = new Set([1, 2, 3, 4])
const b = new Set([3, 4, 5])
console.log(a.intersection(b))
// -> Set { 3, 4 }

同等の処理

const c = new Set()
for (const e of b) {
  if (a.has(e)) {
    c.add(e)
  }
}
console.log(c)
// -> Set { 3, 4 }

Set.prototype.union()

集合 $A$ と集合 $B$ の和集合 $A \cup B$ を返します。

使い方

// 基本的な使い方
const a = new Set([1, 2, 3, 4])
const b = new Set([3, 4, 5])
console.log(a.union(b))
// -> Set { 1, 2, 3, 4, 5 }

同等の処理

const c = new Set()
for (const e of a) {
  c.add(e)
}
for (const e of b) {
  c.add(e)
}
console.log(c)

Set.prototype.difference()

集合 $A$ と集合 $B$ の差集合 $A \setminus B$ を返します。
※ A に含まれていない B の要素があっても OK

使い方

const a = new Set([1, 2, 3, 4])
const b = new Set([3, 4, 5])
console.log(a.difference(b))
// -> Set { 1, 2 }

同等の処理

const c = new Set()
for (const e of a) {
  if (!b.has(e)) {
    c.add(e)
  }
}
console.log(c)
// -> Set { 1, 2 }

Set.prototype.symmetricDifference()

集合 $A$ と集合 $B$ の対称差集合 $(A \cup B) \setminus (A \cap B)$ を返します。

使い方

const a = new Set([1, 2, 3, 4])
const b = new Set([3, 4, 5])
console.log(a.symmetricDifference(b))
// -> Set { 1, 2, 5 }

同等の処理

const c = new Set()
for (const e of a) {
  c.add(e)
}
for (const e of b) {
  c.add(e)
}
for (const e of c) {
  if (a.has(e) && b.has(e)) {
    c.delete(e)
  }
}
console.log(c)
// -> Set { 1, 2, 5 }

Set.prototype.isSubsetOf()

集合 $A$ と集合 $B$ について、$A \subseteq B$ の真偽を返します。

使い方

const a = new Set([1, 2, 3, 4])
const b = new Set([1, 2, 3, 4, 5])
const c = new Set([2, 3])
const d = new Set([4, 5, 6])
const e = new Set([6, 7, 8])
const f = new Set([1, 2, 3, 4])
const g = new Set()
console.log(a.isSubsetOf(b))
// -> true
console.log(a.isSubsetOf(c))
// -> false
console.log(a.isSubsetOf(d))
// -> false
console.log(a.isSubsetOf(e))
// -> false
console.log(a.isSubsetOf(f))
// -> true
console.log(a.isSubsetOf(g))
// -> false

Set.prototype.isDisjointFrom()

集合 $A$ と集合 $B$ について、$A \cap B = \Phi$ の真偽を返します。

使い方

const a = new Set([1, 2, 3, 4])
const b = new Set([1, 2, 3, 4, 5])
const c = new Set([2, 3])
const d = new Set([4, 5, 6])
const e = new Set([6, 7, 8])
const f = new Set([1, 2, 3, 4])
const g = new Set()
console.log(a.isDisjointFrom(b))
// -> false
console.log(a.isDisjointFrom(c))
// -> false
console.log(a.isDisjointFrom(d))
// -> false
console.log(a.isDisjointFrom(e))
// -> true
console.log(a.isDisjointFrom(f))
// -> false
console.log(a.isDisjointFrom(g))
// -> true

Set.prototype.isSupersetOf()

集合 $A$ と集合 $B$ について、$A \supseteq B$ の真偽を返します。

使い方

const a = new Set([1, 2, 3, 4])
const b = new Set([1, 2, 3, 4, 5])
const c = new Set([2, 3])
const d = new Set([4, 5, 6])
const e = new Set([6, 7, 8])
const f = new Set([1, 2, 3, 4])
const g = new Set()
console.log(a.isSupersetOf(b))
// -> false
console.log(a.isSupersetOf(c))
// -> true
console.log(a.isSupersetOf(d))
// -> false
console.log(a.isSupersetOf(e))
// -> false
console.log(a.isSupersetOf(f))
// -> true
console.log(a.isSupersetOf(g))
// -> true

共通事項

いずれのメソッドも元オブジェクトを変更しません。
また、引数側は Set オブジェクトである必要がなく、iterable で OK です。

const a = new Set([1, 2, 3, 4])
const b = new Set([3, 4, 5])
console.log(a.intersection(b))
// -> Set { 3, 4 }

// 元オブジェクトを変更しない
console.log(a, b)
// -> Set { 1, 2, 3, 4 } Set { 3, 4, 5 }

// 引数はSetじゃなくても良い
console.log(a.intersection([1, 3, 5]))
// -> Set { 1, 3 }

検討事項

クラスメソッド Set.union(...iterables)Set.intersection(...iterables) は Proposal に含まれていませんが、検討の余地があるとされています。
Immutable.js にはこれらのクラスメソッドが含まれています。


Polyfill

core-js/proposals/set-methods を読み込んでください。

CommonJS

require('core-js/proposals/set-methods')

ES Modules

import 'core-js/proposals/set-methods'

所感

これらの集合操作を自前で書くことが多かったので結構嬉しい。


参考情報