JavaScript Setの新メソッド完全ガイド - intersection, union, differenceの実践活用
問題
2つの配列から共通要素を抽出したり、結合したり、差分を求める場面は頻繁にあります。
従来はfilter + includesの組み合わせで処理していましたが、コードが冗長で性能も良くありませんでした。
// 従来の方法 - 冗長で遅い
const common = arr1.filter(x => arr2.includes(x));
const merged = [...new Set([...arr1, ...arr2])];
const diff = arr1.filter(x => !arr2.includes(x));
includesが毎回O(n)の探索を行うため、全体的にO(n²)になります。
データが大きくなると明らかに遅くなります。
解決方法
Setに新しく追加された集合演算メソッドを使います。 2024年に主要ブラウザすべてでサポートが完了し、Node.js 22以降で利用可能です。
const frontend = new Set(['React', 'Vue', 'Svelte', 'Angular']);
const liked = new Set(['React', 'Svelte', 'Rust', 'Go']);
// 積集合 - 両方に含まれるもの
frontend.intersection(liked);
// Set {'React', 'Svelte'}
// 和集合 - すべてを結合
frontend.union(liked);
// Set {'React', 'Vue', 'Svelte', 'Angular', 'Rust', 'Go'}
// 差集合 - frontendにだけあるもの
frontend.difference(liked);
// Set {'Vue', 'Angular'}
// 対称差集合 - 片方にだけあるもの
frontend.symmetricDifference(liked);
// Set {'Vue', 'Angular', 'Rust', 'Go'}
比較メソッドも用意されています。
const all = new Set([1, 2, 3, 4, 5]);
const sub = new Set([2, 3]);
const other = new Set([6, 7]);
// 部分集合の確認
sub.isSubsetOf(all); // true
// 上位集合の確認
all.isSupersetOf(sub); // true
// 互いに素の確認(共通要素なし)
all.isDisjointFrom(other); // true
実践的なパターン
権限チェックなどですぐに活用できます。
function hasRequiredPermissions(userPerms, requiredPerms) {
const user = new Set(userPerms);
const required = new Set(requiredPerms);
return required.isSubsetOf(user);
}
const myPerms = ['read', 'write', 'delete'];
const needed = ['read', 'write'];
hasRequiredPermissions(myPerms, needed); // true
タグフィルタリングもシンプルになります。
const selectedTags = new Set(['JavaScript', 'TypeScript']);
const postTags = new Set(['JavaScript', 'React', 'Node.js']);
selectedTags.intersection(postTags).size > 0; // true
ポイント
intersection、union、difference、symmetricDifferenceの4つが核心です- 元のSetを変更せず、新しいSetを返します(イミュータブル)
filter+includesよりも高速 - 内部的にハッシュベースのO(n)処理- Node.js 22+、Chrome 122+、Safari 17+、Firefox 127+でサポート
isSubsetOf、isSupersetOf、isDisjointFromで集合の関係も確認可能