UNPKG

sussy-util

Version:
227 lines (226 loc) 8.97 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const _1 = require("."); /** * A custom Set implementation that ensures unique items with flexible equality checks. * @template T - The type of items stored in the Set. */ class Set { /** * Constructs a new Set instance. * @param {T[]} items - The initial items to populate the set. * @param {CheckFunction<T>} [checkFunction] - Optional equality check function. */ constructor(items, checkFunction) { this.items = new _1.ImprovedArray(); this.checkFunction = (a, b) => a === b; /** * Adds an item to the set if it does not already exist. * @param {T} item - The item to add. */ this.push = (item) => { if (this.has(item)) return; this.items.push(item); }; /** * Removes an item from the set. * @param {T} item - The item to remove. * @returns {boolean} - True if the item was removed, false otherwise. */ this.delete = (item) => { const index = this.items.indexOf(item); if (index < 0) return false; this.items.remove(index); return true; }; /** * Retrieves the item at a given index as an Optional. * @param {number} index - The index of the item. * @returns {Optional<T>} - The item wrapped in an Optional. */ this.get = (index) => { if (index < 0 || index >= this.length()) return _1.Optional.empty(); return _1.Optional.of(this.items[index]); }; /** * Checks if the set is empty. * @returns {boolean} - True if the set is empty, false otherwise. */ this.isEmpty = this.items.isEmpty.bind(this.items); /** * Returns the number of items in the set. * @returns {number} - The number of items in the set. */ this.length = () => this.items.length; /** * Clears all items from the set. */ this.clear = this.items.clear.bind(this.items); /** * Creates a new Set with the same items. * @returns {Set<T>} - A clone of the current set. */ this.clone = () => new Set(this.items, this.checkFunction); /** * Removes an item at a given index. * @param {number} index - The index of the item to remove. * @returns {boolean} - True if the item was removed, false otherwise. */ this.remove = (index) => { if (index < 0 || index >= this.length()) return false; this.items.remove(index); return true; }; /** * Converts the set to an array. * @returns {T[]} - An array representation of the set. */ this.toArray = this.items.clone.bind(this.items); /** * Changes the equality check function. * @param {CheckFunction<T>} predicate - The new equality check function. */ this.changeCheckFunction = (predicate) => { this.checkFunction = predicate; }; /** * Returns a string representation of the set. * @returns {string} - The string representation of the set. */ this.toString = () => `Set: ${this.items.toString()}`; /** * Returns a JSON string representation of the set. * @returns {string} - The JSON string representation of the set. */ this.toJSONString = () => this.items.toJSONString(); /** * Checks if the set contains an item. * @param {T} item - The item to check for. * @returns {boolean} - True if the item is in the set, false otherwise. */ this.has = (item) => this.items.some(this.checkFunction.bind(this, item)); /** * Executes a callback function for each item in the set. * @param {CallBack<T>} callback - The callback function. */ this.forEach = (callback) => this.items.forEach(callback); /** * Executes a callback function for each item in the set (alias for `forEach`). * @param {CallBack<T>} callback - The callback function. */ this.each = (callback) => this.forEach(callback); /** * Merges another set with this set. * @param {Set<T>} set - The set to merge. * @returns {Set<T>} - A new set containing all items from both sets. */ this.merge = (set) => { return new Set([...this.items, ...set.toArray()], this.checkFunction); }; /** * Returns a new set containing items present in this set but not in the provided set. * @param {Set<T>} set - The set to subtract. * @returns {Set<T>} - A new set with subtracted items. */ this.subtract = (set) => { const subtractedItems = this.items.filter((item) => !set.has(item)); return new Set(subtractedItems, this.checkFunction); }; /** * Filters the set based on a predicate. * @param {(item: T, index: number) => boolean} predicate - The predicate function. * @returns {Set<T>} - A new set with items that satisfy the predicate. */ this.filter = (predicate) => { const filteredItems = []; this.forEach((item, i) => { if (!predicate(item, i)) return; filteredItems.push(item); }); return new Set(filteredItems, this.checkFunction); }; /** * Reduces the set to a single value using a reducer function. * @template U * @param {(accumulator: U, currentItem: T, index: number) => U} reducer - The reducer function. * @param {U} initialValue - The initial value for the accumulator. * @returns {U} - The final accumulated value. */ this.reduce = (reducer, initialValue) => { let accumulator = initialValue; this.forEach((item, i) => { accumulator = reducer(accumulator, item, i); }); return accumulator; }; /** * Maps each item in the set to a new value, ensuring uniqueness of mapped items. * @template U * @param {(item: T, index: number) => U} callback - The mapping function. * @returns {Set<U>} - A new set with mapped items. */ this.map = (callback) => { const mappedItems = []; this.forEach((item, i) => { const newItem = callback(item, i); mappedItems.push(newItem); }); return new Set(mappedItems, (a, b) => a === b); }; /** * Returns a new set containing items present in both this set and another set. * @param {Set<T>} set - The set to intersect with. * @returns {Set<T>} - A new set with intersected items. */ this.intersection = (set) => { const intersectionItems = this.items.filter((item) => set.has(item)); return new Set(intersectionItems, this.checkFunction); }; /** * Returns a new set containing all unique items from both sets. * @param {Set<T>} set - The set to unite with. * @returns {Set<T>} - A new set with union items. */ this.union = (set) => { return new Set([...this.items, ...set.toArray()], this.checkFunction); }; /** * Returns a new set containing items that are in either set, but not both. * @param {Set<T>} set - The set to compare with. * @returns {Set<T>} - A new set with symmetric difference items. */ this.symmetricDifference = (set) => { const itemsInThisNotInOther = this.items.filter((item) => !set.has(item)); const itemsInOtherNotInThis = set.toArray().filter((item) => !this.has(item)); return new Set([...itemsInThisNotInOther, ...itemsInOtherNotInThis], this.checkFunction); }; if (checkFunction) this.checkFunction = checkFunction; items.forEach((item) => { if (!this.has(item)) this.items.push(item); }); } /** * Enables iteration over the set using `for...of`. * @returns {Iterator<T>} - An iterator for the set. */ [Symbol.iterator]() { let index = 0; const items = [...this.items]; return { next() { if (index < items.length) { return { value: items[index++], done: false }; } return { value: undefined, done: true }; }, }; } } exports.default = Set;