Socket
Socket
Sign inDemoInstall

fast-ternary-string-set

Package Overview
Dependencies
0
Maintainers
1
Versions
11
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 2.2.0 to 2.3.0

244

lib/index.d.ts

@@ -48,3 +48,3 @@ /**

/**
* Returns the number of unique strings stored in this set.
* Returns the number of unique strings in this set.
*

@@ -63,8 +63,8 @@ * @returns The non-negative integer number of string elements in the set.

* Adding an already present string has no effect.
* If inserting multiple strings in sorted (lexicographic) order, prefer
* `addAll` over this method.
* If inserting multiple strings in sorted order, prefer `addAll`
* over this method.
*
* @param s The non-null string to add.
* @returns This set, allowing chained calls.
* @throws TypeError If the argument is not a string.
* @throws `TypeError` If the argument is not a string.
*/

@@ -74,17 +74,34 @@ add(s: string): this;

/**
* Adds an entire array, or subarray, of strings to this set.
* Adds zero or more strings to this set.
*
* If the array is sorted in ascending order and no other strings have been
* If the collection is sorted in ascending order and no other strings have been
* added to this set, the underlying tree is guaranteed to be balanced, ensuring
* good search performance. If the array is in random order, the tree is *likely*
* good search performance. If the collection is in random order, the tree is *likely*
* to be nearly balanced.
*
* @param strings The non-null array of strings to add.
* @param start The index of the first element to add (inclusive, default is 0).
* @param end The index of the last element to add (exclusive, default is `strings.length`)
* @param strings Zero or more strings to be added to the set.
* @returns This set, allowing chained calls.
* @throws `ReferenceError` If the array is null.
* @throws `TypeError` If any element is not a string or if the start or end are not numbers.
* @throws `RangeError` If the start or end are out of the array bounds.
* @throws `TypeError` If any of the arguments is not a string.
*/
addAll(...strings: string[]): TernaryStringSet;
/**
* Adds an entire array, or subarray, of strings to this set. By default,
* the entire collection is added. If the `start` and/or `end` are specified,
* only the elements in the specified range are added.
*
* If the collection is sorted in ascending order and no other strings have been
* added to this set, the underlying tree is guaranteed to be balanced, ensuring
* good search performance. If the collection is in random order, the tree is *likely*
* to be nearly balanced.
*
* @param strings The non-null collection of strings to add.
* @param start The optional index of the first element to add (inclusive, default is 0).
* @param end The optional index of the last element to add (exclusive, default is all elements)
* @returns This set, allowing chained calls.
* @throws `ReferenceError` If the collection is null.
* @throws `TypeError` If `strings` is not an array or if any element is not a string
* or if the start or end are not integer numbers.
* @throws `RangeError` If the start or end are out of bounds, that is, less than 0
* or greater than `strings.length`.
*/
addAll(strings: readonly string[], start?: number, end?: number): TernaryStringSet;

@@ -112,2 +129,9 @@ private _addAllImpl;

/**
* Removes multiple elements from this set.
*
* @param elements The elements to remove.
* @returns True if every element was present and was removed.
*/
deleteAll(...elements: string[]): boolean;
/**
* Returns all strings in this set that can be composed from combinations of the characters

@@ -186,3 +210,3 @@ * in the specified string. Unlike an anagram, not all pattern characters need to appear for a match

* @returns A (possibly empty) array of elements that pass the test.
* @throws {TypeError} If the predicate is not a function.
* @throws `TypeError` If the predicate is not a function.
*/

@@ -230,2 +254,78 @@ getMatchesOf(predicate: (value: string) => boolean): string[];

/**
* Returns a new set containing all of the strings in this set that pass a
* test implemented by the specified function.
*
* @param predicate A function that accepts strings from this set and returns
* true if the string should be included in the new set.
* @param thisArg An optional value to use as `this` when calling the predicate.
* @returns A new set containing only those elements for which the predicate return
* value is true.
* @throws `TypeError` If the predicate is not a function.
*/
filter(predicate: (value: string, index: number, set: TernaryStringSet) => boolean, thisArg?: unknown): TernaryStringSet;
/**
* Returns a new set populated with the results of calling the specified mapping
* function on each element of this set. Like `Array.map()`, the mapping function
* can return any value, but non-string values will be coerced for
* compatibility with the new set.
*
* @param mapper A function that accepts strings from this set and returns
* the string to be added to the new set.
* @param thisArg An optional value to use as `this` when calling the mapping function.
* @returns A new set containing the results of applying the mapping function to each
* element in this set.
* @throws `TypeError` If the mapping function is not a function.
*/
map(mapper: (value: string, index: number, set: TernaryStringSet) => any, thisArg?: unknown): TernaryStringSet;
/**
* Returns a string that reduces this set to a single accumulated
* value by calling the specified reducer function with each element
* in turn. The reducer is passed the accumulator and the next element
* and returns the new value of the accumulator.
*
* @param reducer A function called with the previous accumulator value,
* the next element to reduce, the element index, and this set.
* @param initialValue An optional initial value for the accumulator.
* If no none is provided, the first element is used.
* @returns The final value of the accumulator.
* @throws `TypeError` If the reducer is not a function or if the set is
* empty and no initial value is provided.
*/
reduce<T>(reducer: (previous: T, current: string, index: number, set: TernaryStringSet) => T, initialValue: T): T;
reduce(reducer: (previous: string, current: string, index: number, set: TernaryStringSet) => string, initialValue?: string): string;
/**
* Returns the first element in this set that satisfies a test implemented by
* the specified function. If no element satisfies the test, the result is
* `undefined`.
*
* @param predicate A function that accepts strings from this set and returns
* true if the string passes the desired test.
* @param thisArg An optional value to use as `this` when calling the predicate.
* @returns The first string to pass the test when tested in sorted order, or `undefined`.
*/
find(predicate: (value: string, index: number, set: TernaryStringSet) => boolean, thisArg?: unknown): string | undefined;
/**
* Returns whether at least one element in this set passes a test implemented
* by the specified function.
*
* @param predicate A function that accepts strings from this set and returns
* true if the string passes the desired test.
* @param thisArg An optional value to use as `this` when calling the predicate.
* @returns True if at least one element in this set passes the test.
* @throws `TypeError` If the predicate is not a function.
*/
some(predicate: (value: string, index: number, set: TernaryStringSet) => boolean, thisArg?: unknown): boolean;
/**
* Returns whether every element in this set passes a test implemented
* by the specified function.
*
* @param predicate A function that accepts strings from this set and returns
* true if the string passes the desired test.
* @param thisArg An optional value to use as `this` when calling the predicate.
* @returns True if at every element in this set passes the test.
* @throws `TypeError` If the predicate is not a function.
*/
every(predicate: (value: string, index: number, set: TernaryStringSet) => boolean, thisArg?: unknown): boolean;
private _predicateImpl;
/**
* Calls the specified callback function once for each string in this set, passing the string

@@ -236,3 +336,3 @@ * and this set. The string is passed as both value and key to align with `Map.forEach`.

* @param callbackFn The function to call for each string.
* @param thisArg Optional value to use as `this` when calling the function.
* @param thisArg An optional value to use as `this` when calling the function.
* @throws `TypeError` If the callback function is not a function.

@@ -273,72 +373,93 @@ */

/**
* Returns whether this set contains exactly the same elements as the specified set.
* If passed an object that is not a `TernaryStringSet`, this method returns false.
* Returns a string that is the concatenation of all strings in this set,
* separated by a comma or the specified separator.
*
* @param separator Optional string to use as separator. Default is `","`.
* @returns A string containing all of the set's elements, in sorted order,
* separated by the specified string.
*/
join(separator?: string): string;
/**
* Returns whether this set contains exactly the same elements as the specified iterable.
* Any object is accepted for comparison; if it is not a set or iterable, the result
* is always `false`.
*
* @param rhs The set (or other object) to compare this set to.
* @returns True if the specified object is also a `TernaryStringSet` and it contains the same elements.
* @returns True if the specified object is iterable, has the same number of elements
* as this set, and this set also contains each of those elements.
*/
equals(rhs: any): boolean;
/**
* Returns whether this set is a subset of the specified set. This set is a subset if every
* element in this set is also contained in the other set. By this definition,
* equal sets are also subsets of each other. To test if this set is a *proper* subset
* of the specified set, use code like this: `lhs.size < rhs.size && lhs.isSubsetOf(rhs)`.
* Returns whether this set is disjoint from the elements of the specified iterable,
* that is, whether this set has no elements in common with the iterable.
*
* @param rhs The iterable whose elements should be tested against this set's.
* @returns True if `this.intersection(rhs)` is empty.
* @throws `TypeError` If the argument is not an iterable.
*/
isDisjointFrom(rhs: Iterable<any>): boolean;
/**
* Returns whether this set is a subset of the elements of the specified iterable,
* that is, whether every element in this set is also an element of the iterable.
*
* @param rhs The set to compare this set to.
* @returns True if this set is a subset of, or equal to, the specified set.
* @throws `TypeError` If the specified set is not a `TernaryStringSet`.
* @returns True if this set is a proper subset of, or equal to, the specified iterable.
* @throws `TypeError` If the argument is not an iterable.
*/
isSubsetOf(rhs: TernaryStringSet): boolean;
isSubsetOf(rhs: Iterable<any>): boolean;
/**
* Returns whether this set is a superset of the specified set. This set is a superset if every
* element in the other set is also contained in this set. By this definition,
* equal sets are also supersets of each other. To test if this set is a *proper* superset
* of the specified set, use code like this: `lhs.size > rhs.size && lhs.isSupersetOf(rhs)`.
* Returns whether this set is a superset of the elements of the specified iterable,
* that is, whether every element of the iterable is also an element in this set.
*
* @param rhs The set to compare this set to.
* @returns True if this set is a superset of, or equal to, the specified set.
* @throws `TypeError` If the specified set is not a `TernaryStringSet`.
* @returns True if this set is a proper superset of, or equal to, the specified iterable.
* @throws `TypeError` If the argument is not an iterable.
*/
isSupersetOf(rhs: TernaryStringSet): boolean;
isSupersetOf(rhs: Iterable<any>): boolean;
/**
* Returns a new set that is the union of this set and the specified set.
* The new set will include any element that is a member of either set.
* Returns a new set that is the union of this set and the elements of the
* specified iterable. The new set will include any element that is a
* member of either.
*
* @param rhs The set to form a union with.
* @returns A new set containing the elements of both sets.
* @throws `TypeError` If the specified set is not a `TernaryStringSet`.
* @param rhs The iterable whose elements should be united with this set.
* @returns A new set containing the elements of both this set and the iterable.
* @throws `TypeError` If the specified target is not iterable or any
* element is not a string.
*/
union(rhs: TernaryStringSet): TernaryStringSet;
union(rhs: Iterable<string>): TernaryStringSet;
/**
* Returns a new set that is the intersection of this set and the specified set.
* The new set will include only those elements that are members of both sets.
* Returns a new set that is the intersection of this set and the elements
* of the specified iterable. The new set will include only those elements
* that are members of both.
*
* @param rhs The set to intersect with this set.
* @returns A new set containing only elements in both sets.
* @throws `TypeError` If the specified set is not a `TernaryStringSet`.
* @param rhs The iterable to intersect with this set.
* @returns A new set containing only elements in both this set and the iterable.
* @throws `TypeError` If the specified target is not iterable.
*/
intersection(rhs: TernaryStringSet): TernaryStringSet;
intersection(rhs: Iterable<any>): TernaryStringSet;
/** @deprecated since 2.2.0, to be removed in 3.0.0. Use `difference` instead. */
subtract(rhs: TernaryStringSet): TernaryStringSet;
/**
* Returns a new set that is the difference of this set and the specified set.
* The new set will include all of the elements of this set *except* for those
* in the specified set.
* Returns a new set that is the difference of this set and the elements
* of the specified iterable. The new set will contain all elements
* that are only members of this set and not both.
*
* @param rhs The set to subtract from this set.
* @returns A new set containing only those elements in this set that are not
* in the specified set.
* @throws `TypeError` If the specified set is not a `TernaryStringSet`.
* @param rhs The iterable whose elements should be subtracted from this set;
* the iterable's elements do not have to be strings.
* @returns A new set containing only those elements in this set and that are not
* in the specified iterable.
* @throws `TypeError` If the specified target is not iterable.
*/
difference(rhs: TernaryStringSet): TernaryStringSet;
difference(rhs: Iterable<any>): TernaryStringSet;
/**
* Returns a new set that is the symmetric difference of this set and the specified set.
* The new set will include all of the elements that are either set, but not in *both* sets.
* Returns a new set that is the symmetric difference of this set and the elements
* of the specified iterable. The new set will include all of the elements that
* are in either, but not in *both*.
*
* @param rhs The set to take the symmetric difference of from this set.
* @returns A new set containing only those elements in this set or the specified set,
* but not both.
* @throws `TypeError` If the specified set is not a `TernaryStringSet`.
* @param rhs The iterable whose elements should be exclusive-or'd with this set.
* @returns A new set containing those elements either in this set or the iterable,
* but not both or neither.
* @throws `TypeError` If the specified target is not iterable.
*/
symmetricDifference(rhs: TernaryStringSet): TernaryStringSet;
symmetricDifference(rhs: Iterable<string>): TernaryStringSet;
/**

@@ -380,7 +501,6 @@ * Returns an iterator over the strings in this set, in ascending lexicographic order.

* than a non-compacted set. The tradeoff is that compact sets cannot be modified.
* Any method that mutates the set, including
* `add`, `addAll`, `balance`, and `delete`
* Any method that mutates the set, such as `add`, `balance`, oe `delete`,
* can therefore cause the set to revert to an non-compacted state.
*
* Compaction is an excellent option if the primary purpose of a set matching
* Compaction is an excellent option if the primary purpose of a set is matching
* against a fixed collection of strings, such as a dictionary. Since

@@ -387,0 +507,0 @@ * compaction and decompaction are expensive operations, it is less attractive

@@ -9,2 +9,3 @@ "use strict";

const CP_MIN_SURROGATE = 0x10000;
const BALANCE_LIMIT = 100;
let REGEX_LIT_STOP;

@@ -18,3 +19,3 @@ let REGEX_LIT_ZERO;

if (source != null) {
if (typeof source[Symbol.iterator] !== "function") {
if (!(source[Symbol.iterator] instanceof Function)) {
throw new TypeError("source object is not iterable");

@@ -28,7 +29,9 @@ }

}
else if (Array.isArray(source)) {
this.addAll(source);
}
else {
this.addAll(Array.from(source));
if (Array.isArray(source)) {
this.addAll(source);
}
else {
this.addAll(...source);
}
}

@@ -97,20 +100,31 @@ }

}
addAll(strings, start = 0, end = strings.length) {
if (strings == null)
throw new ReferenceError("null strings");
if (!Array.isArray(strings)) {
throw new TypeError("strings must be an array");
addAll(...args) {
if (args.length === 0)
return this;
let strings;
let start;
let end;
if (Array.isArray(args[0])) {
strings = args[0];
const len = strings.length;
start = args[1] ?? 0;
end = args[2] ?? len;
if (typeof start !== "number" || start !== Math.trunc(start)) {
throw new TypeError("start must be an integer");
}
if (typeof end !== "number" || end !== Math.trunc(end)) {
throw new TypeError("end must be an integer");
}
if (start < 0 || start > len) {
throw new RangeError("start: " + start);
}
if (end < 0 || end > len) {
throw new RangeError("end: " + end);
}
}
if (typeof start !== "number" || start !== Math.trunc(start)) {
throw new TypeError("start must be an integer");
else {
strings = args;
start = 0;
end = strings.length;
}
if (start < 0 || start > strings.length) {
throw new RangeError("start: " + start);
}
if (typeof end !== "number" || end !== Math.trunc(end)) {
throw new TypeError("end must be an integer");
}
if (end < 0 || end > strings.length) {
throw new RangeError("end: " + end);
}
if (start < end) {

@@ -214,2 +228,9 @@ this._addAllImpl(strings, start, end);

}
deleteAll(...elements) {
let allDeleted = true;
for (const el of elements) {
allDeleted = this.delete(el) && allDeleted;
}
return allDeleted;
}
getArrangementsOf(charPattern) {

@@ -538,4 +559,139 @@ if (charPattern == null)

}
filter(predicate, thisArg) {
if (!(predicate instanceof Function)) {
throw new TypeError("predicate must be a function");
}
if (this._size === 0)
return new TernaryStringSet();
if (thisArg !== undefined)
predicate = predicate.bind(thisArg);
const results = this._cloneDecompacted();
let index = 0;
if (this._hasEmpty) {
if (!predicate("", index++, this)) {
results._hasEmpty = false;
--results._size;
}
}
this._visitCodePoints(0, [], (cp) => {
if (!predicate(String.fromCodePoint(...cp), index++, this)) {
const node = results._hasCodePoints(0, cp, 0);
results._tree[node] &= ~EOS;
--results._size;
}
});
if (results._size === 0) {
results.clear();
}
else if (results._size <= BALANCE_LIMIT) {
results.balance();
}
return results;
}
map(mapper, thisArg) {
if (!(mapper instanceof Function)) {
throw new TypeError("mapper must be a function");
}
if (thisArg !== undefined)
mapper = mapper.bind(thisArg);
const array = this.toArray();
for (let i = 0; i < array.length; ++i) {
array[i] = String(mapper(array[i], i, this));
}
return new TernaryStringSet(array);
}
reduce(reducer, initialValue) {
if (!(reducer instanceof Function)) {
throw new TypeError("reducer must be a function");
}
if (this._size === 0 && initialValue === undefined) {
throw new TypeError("reduce of empty set with no initial value");
}
let index = 0;
let initialized = false;
let accumulator;
if (initialValue !== undefined) {
accumulator = initialValue;
initialized = true;
}
if (this._hasEmpty) {
if (!initialized) {
accumulator = "";
initialized = true;
}
else {
accumulator = reducer(accumulator, "", 0, this);
}
index = 1;
}
this._visitCodePoints(0, [], (cp) => {
const s = String.fromCodePoint(...cp);
if (!initialized) {
++index;
accumulator = s;
initialized = true;
}
else {
accumulator = reducer(accumulator, s, index++, this);
}
});
return accumulator;
}
find(predicate, thisArg) {
if (!(predicate instanceof Function)) {
throw new TypeError("predicate must be a function");
}
if (this._size === 0)
return undefined;
if (thisArg !== undefined)
predicate = predicate.bind(thisArg);
let index = 0;
if (this._hasEmpty && predicate("", index++, this)) {
return "";
}
let result = undefined;
this._searchCodePoints(0, [], (cp) => {
const s = String.fromCodePoint(...cp);
if (predicate(s, index++, this)) {
if (result === undefined) {
result = s;
return true;
}
}
return false;
});
return result;
}
some(predicate, thisArg) {
return this._predicateImpl(true, predicate, thisArg);
}
every(predicate, thisArg) {
return this._predicateImpl(false, predicate, thisArg);
}
_predicateImpl(cond, predicate, thisArg) {
if (!(predicate instanceof Function)) {
throw new TypeError("predicate must be a function");
}
if (this._size === 0)
return !cond;
if (thisArg !== undefined)
predicate = predicate.bind(thisArg);
let index = 0;
if (this._hasEmpty) {
if (cond == !!predicate("", index++, this)) {
return cond;
}
}
let result = !cond;
this._searchCodePoints(0, [], (cp) => {
if (cond == !!predicate(String.fromCodePoint(...cp), index++, this)) {
result = cond;
return true;
}
return false;
});
return result;
}
forEach(callbackFn, thisArg) {
if (typeof callbackFn !== "function") {
if (!(callbackFn instanceof Function)) {
throw new TypeError("callbackFn must be a function");

@@ -587,5 +743,32 @@ }

}
join(separator = ",") {
separator = String(separator);
let result = "";
let first = !this._hasEmpty;
this._visitCodePoints(0, [], (s) => {
if (first) {
first = false;
}
else {
result += separator;
}
result += String.fromCodePoint(...s);
});
return result;
}
equals(rhs) {
if (!(rhs instanceof TernaryStringSet))
return false;
if (this === rhs)
return true;
if (!(rhs instanceof TernaryStringSet)) {
if (rhs == null || !(rhs[Symbol.iterator] instanceof Function)) {
return false;
}
let rhsSize = 0;
for (const el of rhs) {
if (!this.has(el))
return false;
++rhsSize;
}
return this.size === rhsSize;
}
if (this._size !== rhs._size)

@@ -595,2 +778,29 @@ return false;

}
isDisjointFrom(rhs) {
if (this === rhs)
return false;
if (!(rhs instanceof TernaryStringSet)) {
if (rhs == null || !(rhs[Symbol.iterator] instanceof Function)) {
throw new TypeError("rhs is not iterable");
}
for (const el of rhs) {
if (this.has(el))
return false;
}
return true;
}
if (this._size === 0 || rhs._size === 0)
return true;
if (this._hasEmpty && rhs._hasEmpty)
return false;
let disjoint = true;
this._searchCodePoints(0, [], (s) => {
if (rhs._hasCodePoints(0, s, 0) >= 0) {
disjoint = false;
return true;
}
return false;
});
return disjoint;
}
isSubsetOf(rhs) {

@@ -600,3 +810,13 @@ if (this === rhs)

if (!(rhs instanceof TernaryStringSet)) {
throw new TypeError("not a TernaryStringSet");
if (rhs == null || !(rhs[Symbol.iterator] instanceof Function)) {
throw new TypeError("rhs is not iterable");
}
const rhset = rhs instanceof Set ? rhs : new Set(rhs);
if (this._size > rhset.size)
return false;
for (const s of this) {
if (!rhset.has(s))
return false;
}
return true;
}

@@ -618,4 +838,15 @@ if (this._size > rhs._size)

isSupersetOf(rhs) {
if (this === rhs)
return true;
if (!(rhs instanceof TernaryStringSet)) {
throw new TypeError("not a TernaryStringSet");
if (rhs == null || !(rhs[Symbol.iterator] instanceof Function)) {
throw new TypeError("rhs is not iterable");
}
let rhsSize = 0;
for (const el of rhs) {
if (!this.has(el))
return false;
++rhsSize;
}
return this.size >= rhsSize;
}

@@ -626,3 +857,13 @@ return rhs.isSubsetOf(this);

if (!(rhs instanceof TernaryStringSet)) {
throw new TypeError("not a TernaryStringSet");
if (rhs == null || !(rhs[Symbol.iterator] instanceof Function)) {
throw new TypeError("rhs is not iterable");
}
const union = this._cloneDecompacted();
if (Array.isArray(rhs)) {
union.addAll(rhs);
}
else {
union.addAll(...rhs);
}
return union;
}

@@ -644,3 +885,12 @@ if (rhs._size > this._size) {

if (!(rhs instanceof TernaryStringSet)) {
throw new TypeError("not a TernaryStringSet");
if (rhs == null || !(rhs[Symbol.iterator] instanceof Function)) {
throw new TypeError("rhs is not iterable");
}
const intersect = [];
for (const s of rhs) {
if (this.has(s)) {
intersect.push(s);
}
}
return new TernaryStringSet(intersect);
}

@@ -655,3 +905,2 @@ if (rhs._size < this._size) {

}
intersect._hasEmpty && (intersect._hasEmpty = rhs._hasEmpty);
intersect._visitCodePoints(0, [], (s, node) => {

@@ -670,3 +919,10 @@ if (rhs._hasCodePoints(0, s, 0) < 0) {

if (!(rhs instanceof TernaryStringSet)) {
throw new TypeError("not a TernaryStringSet");
if (rhs == null || !(rhs[Symbol.iterator] instanceof Function)) {
throw new TypeError("rhs is not iterable");
}
const diff = this._cloneDecompacted();
for (const s of rhs) {
diff.delete(s);
}
return diff;
}

@@ -688,3 +944,6 @@ const diff = this._cloneDecompacted();

if (!(rhs instanceof TernaryStringSet)) {
throw new TypeError("not a TernaryStringSet");
if (rhs == null || !(rhs[Symbol.iterator] instanceof Function)) {
throw new TypeError("rhs is not iterable");
}
rhs = new TernaryStringSet(rhs);
}

@@ -727,2 +986,3 @@ const diff = this._cloneDecompacted();

let source = this._tree;
this._tree = null;
for (;;) {

@@ -915,3 +1175,3 @@ const compacted = compactionPass(source);

++i;
cps.push(cp);
cps[cps.length] = cp;
}

@@ -918,0 +1178,0 @@ return cps;

{
"name": "fast-ternary-string-set",
"version": "2.2.0",
"version": "2.3.0",
"description": "",

@@ -47,8 +47,8 @@ "keywords": [

"eslint-plugin-prettier": "^3.4.1",
"eslint-plugin-react": "^7.26.1",
"jest": "^27.3.1",
"prettier": "^2.4.1",
"eslint-plugin-react": "^7.27.1",
"jest": "^27.4.3",
"prettier": "^2.5.0",
"ts-jest": "^27.0.7",
"typedoc": "^0.22.6",
"typescript": "^4.4.4"
"typedoc": "^0.22.10",
"typescript": "^4.5.2"
},

@@ -55,0 +55,0 @@ "files": [

@@ -9,3 +9,3 @@ # Fast ternary string set

[API docs](https://cgjennings.github.io/fast-ternary-string-set/classes/TernaryStringSet.html)
**Jump to:** [Features](#features)&nbsp;/ [Installation](#installation)&nbsp;/ [Examples](#examples)&nbsp;/ [Usage notes](#usage-notes)&nbsp;/ [Serialization format](#serialization-format)&nbsp;/ [API docs](https://cgjennings.github.io/fast-ternary-string-set/classes/TernaryStringSet.html)

@@ -17,3 +17,5 @@ ## Features

- Search and iteration methods return elements in ascending sorted order (lexicographic by code point).
- Set relations (equality, subset, superset) and operations (union, intersection, difference, symmetric difference).
- Set relations (equal, subset, superset, disjoint).
- Set operations (union, intersection, difference, symmetric difference).
- `Array`-like functional methods (forEach, filter, map, find, reduce, join, some, every).
- Several approximate matching methods:

@@ -73,3 +75,3 @@ 1. List strings that complete a prefix.

// or alternatively
set.addAll(["aardvark", "beaver", "dog", "fish", "hamster"]);
set.addAll("aardvark", "beaver", "dog", "fish", "hamster");
set.has("cat");

@@ -89,3 +91,3 @@ // => true

// otherSet could be any Iterable<string>, such as a string array
// or even another TernaryStringSet
// or another TernaryStringSet
let otherSet = new Set(["fish", "hippo"]);

@@ -128,3 +130,3 @@ let set = new TernaryStringSet(otherSet);

Get all elements within edit distance 1 of `"cat"`:
Get all elements within edit distance (Levenshtein distance) 1 of `"cat"`:

@@ -143,2 +145,30 @@ ```js

Create a new set with the elements reversed:
```js
set.map((el) => [...el].reverse().join("")).toArray();
// => ["olleH", "rotcoD"] (for example)
```
Get the subset of 4-letter strings:
```js
set.filter((el) => el.length === 4).toArray();
// => ["bank", "cave", "door", "four"] (for example)
```
List elements in reverse sorted order:
```js
set.reduce((acc, el) => `${el}, ${acc}`);
// => "cherry, banana, apple" (for example)
```
Test if any element is longer than 9 characters:
```js
set.add("ambidextrous").some((el) => el.length > 9);
// => true
```
Compare sets:

@@ -229,10 +259,11 @@

`TernaryStringSet` supports a superset of the standard `Set` interface, but it is not a subclass of `Set`.
`TernaryStringSet`s behave like standard JS `Set`s, with minor differences:
JavaScript `Set` objects guarantee that they iterate over elements in the order that they are added.
`TernaryStringSet`s always return results in sorted order.
- They iterate over their elements in sorted order (ascending lexicographic order by code point); `Sets` iterate over objects in the order they were added.
- They support a superset of the standard `Set` interface, but are not a subclass of `Set`. Testing them with `instanceof Set` will return `false`.
- They can contain the empty string, but cannot contain non-strings&mdash;not even `null` or `undefined`.
- Methods that would return a new `Set`, such as `filter` or `union`, return a new `TernaryStringSet`.
- Methods expect that `this` to be a `TernaryStringSet`; they should not be `call`ed with arbitrary objects.
- The `addAll` method accepts either a list of string arguments (like `Set`s), or an `Iterable<string>` with an optional range.
`TernaryStringSet`s can contain the empty string, but cannot contain non-strings.
Not even `null` or `undefined`.
### Tree health

@@ -242,6 +273,6 @@

Adding strings in sorted order produces a worst-case tree structure.
This can be avoided by adding strings all at once using the constructor or `addAll()`.
This can be avoided by adding strings all at once using the constructor or `addAll`.
Given sorted input, both of these methods will produce an optimal tree structure.
If this is not practical, adding strings in random order will typically yield a tree that's "close enough" to balanced for most applications.
Calling `balance()` will rebuild the tree in optimal form, but it can be expensive.
Calling `balance` will rebuild the tree in optimal form, but it can be expensive.

@@ -265,6 +296,6 @@ Since most `TernaryStringSet` methods are recursive, extremely unbalanced trees can provoke "maximum call stack size exceeded" errors.

Calling `compact()` can significantly reduce a set's memory footprint.
For large sets of typical strings, this can reduce the set's footprint by around 50–80%.
However, no strings can be added or deleted without first undoing the compaction (this is done automatically when needed).
Compaction is relatively expensive, but can be a one-time or even ahead-of-time step for many use cases.
Calling `compact` can significantly reduce a set's memory footprint.
For large sets of typical strings, this can reduce the set's footprint by more than 50%.
However, no strings can be added or deleted without first undoing the compaction (this is done automatically).
Compaction is relatively expensive, but can be a one-time or ahead-of-time step for many use cases.

@@ -280,5 +311,5 @@ ### Serialization

1. Create a set and insert the desired strings using `add()` or `addAll()`.
2. Minimize the tree size by calling `balance()` followed by `compact()`.
3. Create the buffer with `toBuffer()` and write the result to a file.
1. Create a set and insert the desired strings using `add` or `addAll`.
2. Minimize the tree size by calling `balance` followed by `compact`.
3. Create the buffer with `toBuffer` and write the result to a file.
4. Optionally, compress the result and configure the server to serve the compressed version where supported by the browser.

@@ -347,3 +378,3 @@

A value of 0 implies that the file is not valid.
Other values would indicate newer versions of the format specification.
Other values would indicate newer versions of the format.

@@ -350,0 +381,0 @@ **Tree flags (int8)**

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc