Skip to content
JavaScript Basics: Compare Collections with Set Operations

JavaScript Basics: Compare Collections with Set Operations

October 18, 2026

Once you have unique values in sets, common collection questions become short operations: what belongs to either set, what belongs to both, and what is missing? Node.js 24 supports the Set composition methods used here. These operations produce new sets or boolean answers without changing the input sets.

These examples were tested on Linux with Node.js v24.19.0. They use built-in APIs only, need no network access, and include assertions that check the results. See the ECMAScript Set specification for the API contract.

Prepare a scratch directory

You need Bash, a text editor, Node.js 24 on your PATH, and the mktemp, rm, and rmdir utilities. Keep using the same terminal. The guarded commands stop the shell if setup fails. Save each named source file as UTF-8; .mjs selects ES modules.

node --version
start_dir="$PWD"
work_dir="$(mktemp -d)" || exit 1
cd -- "$work_dir" || exit 1

The tested runtime prints:

v24.19.0

1. Combine labels and find shared labels

Save this as combine-label-sets.mjs:

import assert from 'node:assert/strict';

const first = new Set(['javascript', 'linux']);
const second = new Set(['linux', 'testing']);
const combined = first.union(second);
const shared = first.intersection(second);
assert.deepEqual([...combined], ['javascript', 'linux', 'testing']);
assert.deepEqual([...shared], ['linux']);
assert.deepEqual([...first], ['javascript', 'linux']);
console.log(`Either: ${[...combined].join(', ')}`);
console.log(`Both: ${[...shared].join(', ')}`);

Run it:

node combine-label-sets.mjs

Output:

Either: javascript, linux, testing
Both: linux

Union includes each distinct value found in either collection. Intersection includes only values present in both. The array spread makes the sets easy to display. Do not assume every set operation has the same ordering rule: intersection can choose iteration order based on the smaller input. Sort the resulting array explicitly when a presentation requires a particular order.

2. Find missing and changed selections

Save this as compare-selected-labels.mjs:

import assert from 'node:assert/strict';

const before = new Set(['draft', 'review']);
const after = new Set(['review', 'published']);
const removed = before.difference(after);
const added = after.difference(before);
const changed = before.symmetricDifference(after);
assert.deepEqual([...removed], ['draft']);
assert.deepEqual([...added], ['published']);
assert.deepEqual([...changed], ['draft', 'published']);
console.log(`Removed: ${[...removed].join(', ')}`);
console.log(`Added: ${[...added].join(', ')}`);
console.log(`Changed: ${[...changed].join(', ')}`);

Run it:

node compare-selected-labels.mjs

Output:

Removed: draft
Added: published
Changed: draft, published

Difference is directional: before.difference(after) is not the same question as after.difference(before). Symmetric difference includes values present in exactly one input, which is handy for spotting changed selections. These examples compare strings. Separate objects with identical fields still count as different values because Set membership compares object identity, not object contents.

3. Check requirements and conflicts

Save this as check-feature-requirements.mjs:

import assert from 'node:assert/strict';

const available = new Set(['read', 'write', 'export']);
const required = new Set(['read', 'export']);
const forbidden = new Set(['delete']);
assert.equal(required.isSubsetOf(available), true);
assert.equal(available.isSupersetOf(required), true);
assert.equal(available.isDisjointFrom(forbidden), true);
assert.equal(new Set(['delete']).isSubsetOf(available), false);
console.log(`Requirements met: ${required.isSubsetOf(available)}`);
console.log(`No conflicts: ${available.isDisjointFrom(forbidden)}`);

Run it:

node check-feature-requirements.mjs

Output:

Requirements met: true
No conflicts: true

A subset check asks whether every required value is available. A disjointness check asks whether there are no shared values. These boolean results are useful for local validation and UI decisions; they are not a replacement for server-side authorization. Method availability differs in older runtimes, so run these examples on Node.js 24 rather than assuming every browser or older Node release supports them.

Clean up

In the same terminal, remove only the example files, return to your original directory, and remove the now-empty scratch directory:

rm -- combine-label-sets.mjs compare-selected-labels.mjs check-feature-requirements.mjs
cd -- "$start_dir" || exit 1
rmdir -- "$work_dir"
unset start_dir work_dir

Acknowledgements

This post was created with assistance from AI.

Last updated on