Whatever message this page gives is out now! Go check it out!
// Array approach — deduplicating 100,000 values
arrayData = [];
for (i = 1; i <= 100000; i++) {
value = randRange(1, 5000);
if (!arrayFind(arrayData, value)) { // O(n) scan every time
arrayAppend(arrayData, value);
}
}arrayFind() scans every existing element until it finds a match or exhausts the array. As the array grows, each check becomes slower. For 100,000 insertions, the cumulative cost can be enormous.// Set approach — same 100,000 values
setData = SetNew();
for (i = 1; i <= 100000; i++) {
value = randRange(1, 5000);
setData.add(value); // O(1), duplicates ignored automatically
}| Situation | Why a set fits |
|---|---|
| You need a collection with no duplicates. | Sets enforce uniqueness automatically. |
| You frequently check whether a value exists. | .has() is O(1) vs arrayFind()'s O(n). |
| You need to combine or compare two groups. | Union, intersection, and difference are built-in. |
| You're building tags, permissions, or feature flags. | Membership-centric data is a natural set. |
| You're deduplicating a list or array. | setNew(array) does it in one call. |
| You're modeling relationships (friends, categories, roles). | Set algebra maps directly to the problem. |
myArray[3]), or when duplicates are meaningful.mySet = setNew();mySet = setNew("ordered");setNew(). All duplicate values are discarded. The result is the deduplicated set of values from the array. This is the fastest way to deduplicate an array.<cfscript>
arr = [1, 2, 3, 4, 5, 5, 4, 3, 2, 1, 23];
uniqueVals = setNew(arr);
writeDump(uniqueVals) // Output: Set with unique values {1, 2, 3, 4, 5, 23}
</cfscript><cfscript>
closure = () => 2 + 3;
mySet = setNew();
mySet.add(closure);
mySet.add(2);
mySet.add("hello");
writeDump(mySet); // Output: Set with values {closure, 2, "hello"}
</cfscript><cfscript>
mySet = setNew();
mySet.add(1);
mySet.add(2);
mySet.add(2); // duplicate — ignored
mySet.add(3);
writeDump(mySet)
// Output: Set with values {1, 2, 3}
</cfscript>true if the value is in the set, false otherwise. This is O(1) — it does not scan the collection.<cfscript>
mySet = setNew();
mySet.add(10);
mySet.add(20);
writeOutput(mySet.has(10)); // true
writeOutput(mySet.has(99)); // false
</cfscript><cfscript>
mySet = setNew();
mySet.add(1);
mySet.add(2);
mySet.add(3);
mySet.delete(2);
writeDump(mySet);
// mySet now contains: {1, 3}
</cfscript><cfscript>
mySet = setNew();
mySet.add("a");
mySet.add("b");
mySet.add("c");
writeOutput(mySet.size()); // 3
</cfscript><cfscript>
mySet = setNew();
mySet.add(1);
mySet.add(2);
writeOutput(mySet.size()); // 2
mySet.clear();
writeOutput(mySet.size()); // 0
</cfscript><cfscript>
set = setNew();
set.add(10);
set.add(20);
set.add(30);
set.add(20); // duplicate — ignored
writeDump(set);
writeOutput("Size: " & set.size()); // 3
writeOutput("Has 20: " & set.has(20)); // true
writeOutput("Has 99: " & set.has(99)); // false
set.delete(20);
writeOutput("After delete, has 20: " & set.has(20)); // false
writeOutput("Size after delete: " & set.size()); // 2
set.clear();
writeOutput("Size after clear: " & set.size()); // 0
</cfscript><cfscript>
setA = setNew("ordered");
setA.add(1); setA.add(2); setA.add(3); setA.add(4);
setB = setNew("ordered");
setB.add(3); setB.add(4); setB.add(5); setB.add(6);
union = setUnion(setA, setB);
writeDump(union); // {1, 2, 3, 4, 5, 6}
</cfscript>intersection = setIntersection(setA, setB);
writeDump(intersection); // {3, 4}setDifference(A, B) ≠ setDifference(B, A).diff = setDifference(setA, setB);
writeDump(diff); // {1, 2}symDiff = setSymmetricDifference(setA, setB);
writeDump(symDiff); // {1, 2, 5, 6}true if the two sets share no common elements — their intersection is empty.<cfscript>
bluetoothProducts = SetNew(["Mouse X", "Headphones Z", "Speaker Q"]);
usbCProducts = SetNew(["Laptop A", "Charger B", "Hub C"]);
if (setIsDisjointFrom(bluetoothProducts, usbCProducts)) {
writeOutput("Bluetooth and USB-C are separate categories");
}
</cfscript>for...in loop to iterate over every element in a set:mySet = setNew("ordered");
mySet.add("Alice");
mySet.add("Bob");
mySet.add("Charlie");
for (name in mySet) {
writeOutput(name & "<br>");
}
// Alice
// Bob
// CharliesetNew("ordered") if you need to process elements in insertion order.setA = setNew("ordered");
setA.add(10); setA.add(20); setA.add(30);
arr = setA.ToArray();
writeDump(arr); // [10, 20, 30]friends = setNew();
friends.add("Alice");
friends.add("Bob");
friends.add("Charlie");
writeOutput(setToList(friends, ", ")); // "Alice, Bob, Charlie"setNew() and it becomes a set, with duplicates automatically removed:rawList = ["red", "blue", "red", "green", "blue", "red"];
uniqueColors = setNew(rawList);
writeOutput(uniqueColors.size()); // 3<cfscript>
// Tags from multiple blog posts — may contain duplicates
allTags = ["cfml", "api", "json", "cfml", "rest", "api", "performance"];
uniqueTags = setNew(allTags);
writeOutput("Unique tags: " & setToList(uniqueTags, ", "));
// cfml, api, json, rest, performance
</cfscript><cfscript>
// Permissions granted by roles
adminPerms = SetNew(["read", "write", "delete", "publish"]);
editorPerms = SetNew(["read", "write", "publish"]);
viewerPerms = SetNew(["read"]);
// What can an admin do that an editor can't?
adminOnly = setDifference(adminPerms, editorPerms);
writeOutput(setToList(adminOnly, ", ")); // delete
// What do admin and editor share?
shared = setIntersection(adminPerms, editorPerms);
writeOutput(setToList(shared, ", ")); // read, write, publish
</cfscript><cfscript>
wirelessProducts = SetNew(["Laptop A", "Mouse X", "Keyboard Y", "Headphones Z"]);
bluetoothProducts = SetNew(["Mouse X", "Headphones Z", "Speaker Q"]);
usbCProducts = SetNew(["Laptop A", "Charger B", "Hub C"]);
// Products with BOTH wireless AND Bluetooth
wirelessBluetooth = setIntersection(wirelessProducts, bluetoothProducts);
writeOutput("Wireless + Bluetooth: ");
writeDump(wirelessBluetooth);
// {Mouse X, Headphones Z}
// Wireless products that DON'T have Bluetooth
wirelessOnly = setDifference(wirelessProducts, bluetoothProducts);
writeOutput("Wireless only: ");
writeDump(wirelessOnly);
// {Laptop A, Keyboard Y}
// Products with wireless OR USB-C
modernProducts = setUnion(wirelessProducts, usbCProducts);
writeOutput("Wireless OR USB-C: ");
writeDump(modernProducts);
// {Laptop A, Mouse X, Keyboard Y, Headphones Z, Charger B, Hub C}
// Confirm Bluetooth and USB-C don't overlap
if (setIsDisjointFrom(bluetoothProducts, usbCProducts)) {
writeOutput("Bluetooth and USB-C are separate categories");
}
</cfscript><cfscript>
// User's current friends
userFriends = SetNew(["Alice", "Bob", "Charlie"]);
// Friends of each friend
aliceFriends = SetNew(["Bob", "David", "Eve"]);
bobFriends = SetNew(["Alice", "Frank", "Grace"]);
charlieFriends = SetNew(["Alice", "David", "Henry"]);
// Collect all friends-of-friends using union
friendsOfFriends = setNew();
for (friend in userFriends) {
if (friend == "Alice") friendsOfFriends = setUnion(friendsOfFriends, aliceFriends);
if (friend == "Bob") friendsOfFriends = setUnion(friendsOfFriends, bobFriends);
if (friend == "Charlie") friendsOfFriends = setUnion(friendsOfFriends, charlieFriends);
}
// Remove people the user already knows → people to suggest
suggestions = setDifference(friendsOfFriends, userFriends);
writeOutput("Friend suggestions: " & setToList(suggestions, ", "));
// David, Eve, Frank, Grace, Henry
</cfscript>| Operation | Array | Set |
|---|---|---|
| Add element | O(1) | O(1) |
| Check membership | O(n) via arrayFind() | O(1) via .has() |
| Remove element | O(n) to find, then shift | O(1) via .delete() |
| Union of two collections | O(n²) with manual dedup | O(n) via setUnion() |
| Intersection | O(n²) nested loops | O(n) via setIntersection() |
| Deduplication | O(n²) arrayFind per item | O(n) setNew(array) |
<cfscript>
// Array: check before each insert
startTime = getTickCount();
arrayData = [];
for (i = 1; i <= 100000; i++) {
value = randRange(1, 5000);
if (!arrayFind(arrayData, value)) {
arrayAppend(arrayData, value);
}
}
arrayTime = getTickCount() - startTime;
writeOutput("Array: " & arrayTime & "ms");
// Set: just add — duplicates handled automatically
startTime = getTickCount();
setData = SetNew();
for (i = 1; i <= 100000; i++) {
value = randRange(1, 5000);
setData.add(value);
}
setTime = getTickCount() - startTime;
writeOutput("Set: " & setTime & "ms");
writeOutput("Set is " & numberFormat(arrayTime / setTime, "0.00") & "x faster");
// Typical result: 50–100x faster
</cfscript>| Function | Description |
|---|---|
setNew() | Create an empty unordered set. |
setNew("ordered") | Create an empty ordered set (preserves insertion order). |
setNew(array) | Create a set from an array, removing duplicates. |
| Method | Returns | Description |
|---|---|---|
.add(value) | void | Add a value; no-op if already present. |
.has(value) | boolean | true if value is in the set. |
.delete(value) | void | Remove a value; no-op if not present. |
.size() | number | Number of elements in the set. |
.clear() | void | Remove all elements. |
.ToArray() | array | Convert the set to a ColdFusion array. |
| Function | Returns | Description |
|---|---|---|
setUnion(setA, setB) | set | All elements in A or B (or both). |
setIntersection(setA, setB) | set | Only elements in both A and B. |
setDifference(setA, setB) | set | Elements in A that are not in B. |
setSymmetricDifference(setA, setB) | set | Elements in either A or B, but not both. |
setIsDisjointFrom(setA, setB) | boolean | true if A and B share no elements. |
setToList(set, delimiter) | string | Joins all elements with the given delimiter. |