Created
July 19, 2025 14:56
-
-
Save DeveloperOfficeCom/147b539d6b54d5ac2123d6b3c10c9381 to your computer and use it in GitHub Desktop.
UniqueSet function for ColdFusion/Lucee - Set data structure for unique values with set operations
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!--- | |
| UNIQUESET Function | |
| Description: Creates a set data structure that stores only unique values, similar to Python's set() | |
| or JavaScript's Set(). Automatically prevents duplicates and provides set operations like union, | |
| intersection, and difference. | |
| Parameters: | |
| - initialData: Optional data to initialize the set (array, string, or delimited list) (optional) | |
| - delimiter: If initialData is a string, the delimiter to split on (optional, default: ",") | |
| Returns: Set object with methods for unique value operations | |
| Usage: | |
| <cfset mySet = uniqueSet()> | |
| <cfset mySet = uniqueSet([1, 2, 2, 3])> | |
| <cfset mySet = uniqueSet("a,b,b,c", ",")> | |
| Examples: | |
| uniqueSet([1, 2, 2, 3]).toArray() returns [1, 2, 3] | |
| uniqueSet().add("apple").add("banana").size() returns 2 | |
| setA.union(setB) returns combined unique values | |
| Author: DeveloperOffice.com | |
| Language: ColdFusion/Lucee | |
| License: MIT (https://opensource.org/licenses/MIT) | |
| Version: 1.0 | |
| ---> | |
| <cffunction name="uniqueSet" returntype="struct" output="false"> | |
| <cfargument name="initialData" type="any" required="false"> | |
| <cfargument name="delimiter" type="string" required="false" default=","> | |
| <!--- Internal storage using struct for fast lookups ---> | |
| <cfset var data = structNew()> | |
| <cfset var insertionOrder = arrayNew(1)> | |
| <!--- Initialize with provided data ---> | |
| <cfif structKeyExists(arguments, "initialData")> | |
| <cfif isArray(arguments.initialData)> | |
| <!--- Initialize from array ---> | |
| <cfloop from="1" to="#arrayLen(arguments.initialData)#" index="i"> | |
| <cfset var value = arguments.initialData[i]> | |
| <cfset var key = toString(value)> | |
| <cfif NOT structKeyExists(data, key)> | |
| <cfset data[key] = value> | |
| <cfset arrayAppend(insertionOrder, value)> | |
| </cfif> | |
| </cfloop> | |
| <cfelseif isSimpleValue(arguments.initialData)> | |
| <!--- Initialize from delimited string ---> | |
| <cfif len(trim(arguments.initialData)) GT 0> | |
| <cfset var items = listToArray(arguments.initialData, arguments.delimiter)> | |
| <cfloop from="1" to="#arrayLen(items)#" index="i"> | |
| <cfset var value = trim(items[i])> | |
| <cfset var key = toString(value)> | |
| <cfif NOT structKeyExists(data, key)> | |
| <cfset data[key] = value> | |
| <cfset arrayAppend(insertionOrder, value)> | |
| </cfif> | |
| </cfloop> | |
| </cfif> | |
| </cfif> | |
| </cfif> | |
| <!--- Create the set wrapper ---> | |
| <cfset var setWrapper = structNew()> | |
| <cfset setWrapper._data = data> | |
| <cfset setWrapper._order = insertionOrder> | |
| <!--- Add method to add values ---> | |
| <cfset setWrapper.add = function(value) { | |
| <cfset var key = toString(arguments.value)> | |
| <cfif NOT structKeyExists(this._data, key)> | |
| <cfset this._data[key] = arguments.value> | |
| <cfset arrayAppend(this._order, arguments.value)> | |
| </cfif> | |
| <cfreturn this> | |
| }> | |
| <!--- Remove method to remove values ---> | |
| <cfset setWrapper.remove = function(value) { | |
| <cfset var key = toString(arguments.value)> | |
| <cfif structKeyExists(this._data, key)> | |
| <cfset structDelete(this._data, key)> | |
| <!--- Remove from insertion order ---> | |
| <cfset var index = arrayFind(this._order, arguments.value)> | |
| <cfif index GT 0> | |
| <cfset arrayDeleteAt(this._order, index)> | |
| </cfif> | |
| <cfreturn true> | |
| </cfif> | |
| <cfreturn false> | |
| }> | |
| <!--- Has method to check if value exists ---> | |
| <cfset setWrapper.has = function(value) { | |
| <cfset var key = toString(arguments.value)> | |
| <cfreturn structKeyExists(this._data, key)> | |
| }> | |
| <!--- Size method to get count of unique values ---> | |
| <cfset setWrapper.size = function() { | |
| <cfreturn structCount(this._data)> | |
| }> | |
| <!--- Clear method to remove all values ---> | |
| <cfset setWrapper.clear = function() { | |
| <cfset structClear(this._data)> | |
| <cfset arrayClear(this._order)> | |
| <cfreturn this> | |
| }> | |
| <!--- ToArray method to get array of unique values ---> | |
| <cfset setWrapper.toArray = function() { | |
| <cfreturn duplicate(this._order)> | |
| }> | |
| <!--- ToList method to get delimited string ---> | |
| <cfset setWrapper.toList = function(delimiter) { | |
| <cfset var delim = ","> | |
| <cfif structKeyExists(arguments, "delimiter")> | |
| <cfset delim = arguments.delimiter> | |
| </cfif> | |
| <cfreturn arrayToList(this._order, delim)> | |
| }> | |
| <!--- Union method to combine with another set ---> | |
| <cfset setWrapper.union = function(otherSet) { | |
| <cfset var result = uniqueSet()> | |
| <!--- Add all values from this set ---> | |
| <cfloop from="1" to="#arrayLen(this._order)#" index="i"> | |
| <cfset result.add(this._order[i])> | |
| </cfloop> | |
| <!--- Add all values from other set ---> | |
| <cfif isStruct(arguments.otherSet) AND structKeyExists(arguments.otherSet, "_order")> | |
| <cfloop from="1" to="#arrayLen(arguments.otherSet._order)#" index="i"> | |
| <cfset result.add(arguments.otherSet._order[i])> | |
| </cfloop> | |
| <cfelseif isArray(arguments.otherSet)> | |
| <cfloop from="1" to="#arrayLen(arguments.otherSet)#" index="i"> | |
| <cfset result.add(arguments.otherSet[i])> | |
| </cfloop> | |
| </cfif> | |
| <cfreturn result> | |
| }> | |
| <!--- Intersection method to find common values ---> | |
| <cfset setWrapper.intersection = function(otherSet) { | |
| <cfset var result = uniqueSet()> | |
| <!--- Check each value in this set against other set ---> | |
| <cfloop from="1" to="#arrayLen(this._order)#" index="i"> | |
| <cfset var value = this._order[i]> | |
| <cfset var found = false> | |
| <cfif isStruct(arguments.otherSet) AND structKeyExists(arguments.otherSet, "has")> | |
| <cfset found = arguments.otherSet.has(value)> | |
| <cfelseif isArray(arguments.otherSet)> | |
| <cfset found = arrayContains(arguments.otherSet, value)> | |
| </cfif> | |
| <cfif found> | |
| <cfset result.add(value)> | |
| </cfif> | |
| </cfloop> | |
| <cfreturn result> | |
| }> | |
| <!--- Difference method to find values only in this set ---> | |
| <cfset setWrapper.difference = function(otherSet) { | |
| <cfset var result = uniqueSet()> | |
| <!--- Check each value in this set ---> | |
| <cfloop from="1" to="#arrayLen(this._order)#" index="i"> | |
| <cfset var value = this._order[i]> | |
| <cfset var found = false> | |
| <cfif isStruct(arguments.otherSet) AND structKeyExists(arguments.otherSet, "has")> | |
| <cfset found = arguments.otherSet.has(value)> | |
| <cfelseif isArray(arguments.otherSet)> | |
| <cfset found = arrayContains(arguments.otherSet, value)> | |
| </cfif> | |
| <cfif NOT found> | |
| <cfset result.add(value)> | |
| </cfif> | |
| </cfloop> | |
| <cfreturn result> | |
| }> | |
| <!--- IsSubset method to check if this set is subset of another ---> | |
| <cfset setWrapper.isSubset = function(otherSet) { | |
| <cfloop from="1" to="#arrayLen(this._order)#" index="i"> | |
| <cfset var value = this._order[i]> | |
| <cfset var found = false> | |
| <cfif isStruct(arguments.otherSet) AND structKeyExists(arguments.otherSet, "has")> | |
| <cfset found = arguments.otherSet.has(value)> | |
| <cfelseif isArray(arguments.otherSet)> | |
| <cfset found = arrayContains(arguments.otherSet, value)> | |
| </cfif> | |
| <cfif NOT found> | |
| <cfreturn false> | |
| </cfif> | |
| </cfloop> | |
| <cfreturn true> | |
| }> | |
| <!--- IsSuperset method to check if this set contains another set ---> | |
| <cfset setWrapper.isSuperset = function(otherSet) { | |
| <cfif isStruct(arguments.otherSet) AND structKeyExists(arguments.otherSet, "_order")> | |
| <cfloop from="1" to="#arrayLen(arguments.otherSet._order)#" index="i"> | |
| <cfif NOT this.has(arguments.otherSet._order[i])> | |
| <cfreturn false> | |
| </cfif> | |
| </cfloop> | |
| <cfelseif isArray(arguments.otherSet)> | |
| <cfloop from="1" to="#arrayLen(arguments.otherSet)#" index="i"> | |
| <cfif NOT this.has(arguments.otherSet[i])> | |
| <cfreturn false> | |
| </cfif> | |
| </cfloop> | |
| </cfif> | |
| <cfreturn true> | |
| }> | |
| <!--- Equals method to check if sets are equal ---> | |
| <cfset setWrapper.equals = function(otherSet) { | |
| <cfif isStruct(arguments.otherSet) AND structKeyExists(arguments.otherSet, "size")> | |
| <cfreturn this.size() EQ arguments.otherSet.size() AND this.isSubset(arguments.otherSet)> | |
| </cfif> | |
| <cfreturn false> | |
| }> | |
| <!--- IsEmpty method ---> | |
| <cfset setWrapper.isEmpty = function() { | |
| <cfreturn this.size() EQ 0> | |
| }> | |
| <cfreturn setWrapper> | |
| </cffunction> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment