@procedures/collections 0.0.0-stage → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/LICENSE +21 -0
- package/README.md +394 -2
- package/dist/.tsbuildinfo +1 -0
- package/dist/async/async-queue.d.ts +155 -0
- package/dist/async/async-queue.d.ts.map +1 -0
- package/dist/async/async-queue.js +342 -0
- package/dist/async/async-queue.js.map +1 -0
- package/dist/async/channels.d.ts +188 -0
- package/dist/async/channels.d.ts.map +1 -0
- package/dist/async/channels.js +314 -0
- package/dist/async/channels.js.map +1 -0
- package/dist/behaviors/bounded.d.ts +79 -0
- package/dist/behaviors/bounded.d.ts.map +1 -0
- package/dist/behaviors/bounded.js +384 -0
- package/dist/behaviors/bounded.js.map +1 -0
- package/dist/behaviors/composite.d.ts +17 -0
- package/dist/behaviors/composite.d.ts.map +1 -0
- package/dist/behaviors/composite.js +93 -0
- package/dist/behaviors/composite.js.map +1 -0
- package/dist/behaviors/evented.d.ts +154 -0
- package/dist/behaviors/evented.d.ts.map +1 -0
- package/dist/behaviors/evented.js +299 -0
- package/dist/behaviors/evented.js.map +1 -0
- package/dist/behaviors/lru.d.ts +84 -0
- package/dist/behaviors/lru.d.ts.map +1 -0
- package/dist/behaviors/lru.js +376 -0
- package/dist/behaviors/lru.js.map +1 -0
- package/dist/behaviors/readonly.d.ts +73 -0
- package/dist/behaviors/readonly.d.ts.map +1 -0
- package/dist/behaviors/readonly.js +177 -0
- package/dist/behaviors/readonly.js.map +1 -0
- package/dist/behaviors/safe.d.ts +163 -0
- package/dist/behaviors/safe.d.ts.map +1 -0
- package/dist/behaviors/safe.js +176 -0
- package/dist/behaviors/safe.js.map +1 -0
- package/dist/behaviors/synchronized.d.ts +88 -0
- package/dist/behaviors/synchronized.d.ts.map +1 -0
- package/dist/behaviors/synchronized.js +285 -0
- package/dist/behaviors/synchronized.js.map +1 -0
- package/dist/behaviors/ttl.d.ts +118 -0
- package/dist/behaviors/ttl.d.ts.map +1 -0
- package/dist/behaviors/ttl.js +354 -0
- package/dist/behaviors/ttl.js.map +1 -0
- package/dist/contracts/model.d.ts +29 -0
- package/dist/contracts/model.d.ts.map +1 -0
- package/dist/contracts/model.js +26 -0
- package/dist/contracts/model.js.map +1 -0
- package/dist/core/effects.d.ts +176 -0
- package/dist/core/effects.d.ts.map +1 -0
- package/dist/core/effects.js +180 -0
- package/dist/core/effects.js.map +1 -0
- package/dist/core/events.d.ts +192 -0
- package/dist/core/events.d.ts.map +1 -0
- package/dist/core/events.js +291 -0
- package/dist/core/events.js.map +1 -0
- package/dist/core/middleware.d.ts +231 -0
- package/dist/core/middleware.d.ts.map +1 -0
- package/dist/core/middleware.js +161 -0
- package/dist/core/middleware.js.map +1 -0
- package/dist/core/policies.d.ts +220 -0
- package/dist/core/policies.d.ts.map +1 -0
- package/dist/core/policies.js +48 -0
- package/dist/core/policies.js.map +1 -0
- package/dist/core/traits.d.ts +142 -0
- package/dist/core/traits.d.ts.map +1 -0
- package/dist/core/traits.js +8 -0
- package/dist/core/traits.js.map +1 -0
- package/dist/fx/collectors.d.ts +193 -0
- package/dist/fx/collectors.d.ts.map +1 -0
- package/dist/fx/collectors.js +375 -0
- package/dist/fx/collectors.js.map +1 -0
- package/dist/fx/iter.d.ts +166 -0
- package/dist/fx/iter.d.ts.map +1 -0
- package/dist/fx/iter.js +421 -0
- package/dist/fx/iter.js.map +1 -0
- package/dist/impl/array-deque.d.ts +112 -0
- package/dist/impl/array-deque.d.ts.map +1 -0
- package/dist/impl/array-deque.js +380 -0
- package/dist/impl/array-deque.js.map +1 -0
- package/dist/impl/array-list.d.ts +101 -0
- package/dist/impl/array-list.d.ts.map +1 -0
- package/dist/impl/array-list.js +387 -0
- package/dist/impl/array-list.js.map +1 -0
- package/dist/impl/hash-map.d.ts +149 -0
- package/dist/impl/hash-map.d.ts.map +1 -0
- package/dist/impl/hash-map.js +473 -0
- package/dist/impl/hash-map.js.map +1 -0
- package/dist/impl/hash-set.d.ts +125 -0
- package/dist/impl/hash-set.d.ts.map +1 -0
- package/dist/impl/hash-set.js +264 -0
- package/dist/impl/hash-set.js.map +1 -0
- package/dist/impl/linked-hash-map.d.ts +141 -0
- package/dist/impl/linked-hash-map.d.ts.map +1 -0
- package/dist/impl/linked-hash-map.js +442 -0
- package/dist/impl/linked-hash-map.js.map +1 -0
- package/dist/impl/linked-list.d.ts +109 -0
- package/dist/impl/linked-list.d.ts.map +1 -0
- package/dist/impl/linked-list.js +494 -0
- package/dist/impl/linked-list.js.map +1 -0
- package/dist/impl/priority-queue.d.ts +139 -0
- package/dist/impl/priority-queue.d.ts.map +1 -0
- package/dist/impl/priority-queue.js +343 -0
- package/dist/impl/priority-queue.js.map +1 -0
- package/dist/impl/tree-map.d.ts +153 -0
- package/dist/impl/tree-map.d.ts.map +1 -0
- package/dist/impl/tree-map.js +788 -0
- package/dist/impl/tree-map.js.map +1 -0
- package/dist/impl/tree-set.d.ts +112 -0
- package/dist/impl/tree-set.d.ts.map +1 -0
- package/dist/impl/tree-set.js +374 -0
- package/dist/impl/tree-set.js.map +1 -0
- package/dist/index.d.ts +106 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +139 -0
- package/dist/index.js.map +1 -0
- package/dist/interfaces/collection.d.ts +119 -0
- package/dist/interfaces/collection.d.ts.map +1 -0
- package/dist/interfaces/collection.js +8 -0
- package/dist/interfaces/collection.js.map +1 -0
- package/dist/interfaces/list.d.ts +247 -0
- package/dist/interfaces/list.d.ts.map +1 -0
- package/dist/interfaces/list.js +8 -0
- package/dist/interfaces/list.js.map +1 -0
- package/dist/interfaces/map.d.ts +344 -0
- package/dist/interfaces/map.d.ts.map +1 -0
- package/dist/interfaces/map.js +8 -0
- package/dist/interfaces/map.js.map +1 -0
- package/dist/interfaces/queue.d.ts +304 -0
- package/dist/interfaces/queue.d.ts.map +1 -0
- package/dist/interfaces/queue.js +8 -0
- package/dist/interfaces/queue.js.map +1 -0
- package/dist/interfaces/set.d.ts +137 -0
- package/dist/interfaces/set.d.ts.map +1 -0
- package/dist/interfaces/set.js +8 -0
- package/dist/interfaces/set.js.map +1 -0
- package/dist/register.d.ts +8 -0
- package/dist/register.d.ts.map +1 -0
- package/dist/register.js +8 -0
- package/dist/register.js.map +1 -0
- package/dist/storage/index.d.ts +15 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +14 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/interface.d.ts +141 -0
- package/dist/storage/interface.d.ts.map +1 -0
- package/dist/storage/interface.js +23 -0
- package/dist/storage/interface.js.map +1 -0
- package/dist/storage/memory.d.ts +68 -0
- package/dist/storage/memory.d.ts.map +1 -0
- package/dist/storage/memory.js +154 -0
- package/dist/storage/memory.js.map +1 -0
- package/dist/utils/defaults.d.ts +135 -0
- package/dist/utils/defaults.d.ts.map +1 -0
- package/dist/utils/defaults.js +322 -0
- package/dist/utils/defaults.js.map +1 -0
- package/dist/utils/factories.d.ts +144 -0
- package/dist/utils/factories.d.ts.map +1 -0
- package/dist/utils/factories.js +293 -0
- package/dist/utils/factories.js.map +1 -0
- package/dist/utils/helpers.d.ts +137 -0
- package/dist/utils/helpers.d.ts.map +1 -0
- package/dist/utils/helpers.js +221 -0
- package/dist/utils/helpers.js.map +1 -0
- package/package.json +68 -3
- package/src/async/async-queue.ts +417 -0
- package/src/async/channels.ts +374 -0
- package/src/behaviors/bounded.ts +477 -0
- package/src/behaviors/composite.ts +99 -0
- package/src/behaviors/evented.ts +464 -0
- package/src/behaviors/lru.ts +447 -0
- package/src/behaviors/readonly.ts +224 -0
- package/src/behaviors/safe.ts +372 -0
- package/src/behaviors/synchronized.ts +316 -0
- package/src/behaviors/ttl.ts +462 -0
- package/src/contracts/model.ts +44 -0
- package/src/core/effects.ts +323 -0
- package/src/core/events.ts +356 -0
- package/src/core/middleware.ts +415 -0
- package/src/core/policies.ts +316 -0
- package/src/core/traits.ts +164 -0
- package/src/fx/collectors.ts +500 -0
- package/src/fx/iter.ts +536 -0
- package/src/impl/array-deque.ts +463 -0
- package/src/impl/array-list.ts +490 -0
- package/src/impl/hash-map.ts +623 -0
- package/src/impl/hash-set.ts +342 -0
- package/src/impl/linked-hash-map.ts +572 -0
- package/src/impl/linked-list.ts +606 -0
- package/src/impl/priority-queue.ts +448 -0
- package/src/impl/tree-map.ts +912 -0
- package/src/impl/tree-set.ts +469 -0
- package/src/index.ts +277 -0
- package/src/interfaces/collection.ts +141 -0
- package/src/interfaces/list.ts +281 -0
- package/src/interfaces/map.ts +405 -0
- package/src/interfaces/queue.ts +353 -0
- package/src/interfaces/set.ts +158 -0
- package/src/register.ts +8 -0
- package/src/storage/index.ts +16 -0
- package/src/storage/interface.ts +179 -0
- package/src/storage/memory.ts +180 -0
- package/src/utils/defaults.ts +345 -0
- package/src/utils/factories.ts +357 -0
- package/src/utils/helpers.ts +248 -0
|
@@ -0,0 +1,469 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TreeSet - Red-black tree based sorted set implementation.
|
|
3
|
+
*
|
|
4
|
+
* Implements a sorted set using TreeMap as the backing structure.
|
|
5
|
+
* Mirrors java.util.TreeSet.
|
|
6
|
+
*
|
|
7
|
+
* Key features:
|
|
8
|
+
* - O(log n) add, remove, contains
|
|
9
|
+
* - Elements maintained in sorted order (natural or custom comparator)
|
|
10
|
+
* - Navigation methods (floor, ceiling, lower, higher)
|
|
11
|
+
* - Range view operations (subSet, headSet, tailSet)
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* const set = treeSet<string>()
|
|
15
|
+
* set.add('c')
|
|
16
|
+
* set.add('a')
|
|
17
|
+
* set.add('b')
|
|
18
|
+
* // Iteration order: a, b, c (sorted)
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* // Custom comparator for descending order
|
|
22
|
+
* const set = treeSet<number>({
|
|
23
|
+
* compare: (a, b) => b - a
|
|
24
|
+
* })
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
import type { SortedSet, NavigableSet } from "../interfaces/set.js";
|
|
28
|
+
import type { Eq, Compare } from "../core/traits.js";
|
|
29
|
+
import { TreeMap } from "./tree-map.js";
|
|
30
|
+
import { defaultEq, defaultCompare } from "../utils/defaults.js";
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Dummy value used for TreeMap backing.
|
|
34
|
+
*/
|
|
35
|
+
const PRESENT = true;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Options for creating a TreeSet.
|
|
39
|
+
*/
|
|
40
|
+
export interface TreeSetOptions<T> {
|
|
41
|
+
/**
|
|
42
|
+
* Comparison function for elements.
|
|
43
|
+
* @default defaultCompare
|
|
44
|
+
*/
|
|
45
|
+
compare?: Compare<T>;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Equality function for elements.
|
|
49
|
+
* @default defaultEq
|
|
50
|
+
*/
|
|
51
|
+
eq?: Eq<T>;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* TreeSet<T> - Red-black tree based sorted set.
|
|
56
|
+
*
|
|
57
|
+
* Maintains elements in sorted order using a TreeMap as backing structure.
|
|
58
|
+
* Provides O(log n) operations and navigation methods.
|
|
59
|
+
*/
|
|
60
|
+
export class TreeSet<T> implements NavigableSet<T> {
|
|
61
|
+
private readonly _map: TreeMap<T, boolean>;
|
|
62
|
+
private readonly _compare: Compare<T>;
|
|
63
|
+
private readonly _eq: Eq<T>;
|
|
64
|
+
|
|
65
|
+
constructor(options: TreeSetOptions<T> = {}) {
|
|
66
|
+
const {
|
|
67
|
+
compare = defaultCompare,
|
|
68
|
+
eq = defaultEq,
|
|
69
|
+
} = options;
|
|
70
|
+
|
|
71
|
+
this._compare = compare;
|
|
72
|
+
this._eq = eq;
|
|
73
|
+
this._map = new TreeMap<T, boolean>({
|
|
74
|
+
compare,
|
|
75
|
+
eq,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// ========================================================================
|
|
80
|
+
// Size and state
|
|
81
|
+
// ========================================================================
|
|
82
|
+
|
|
83
|
+
get size(): number {
|
|
84
|
+
return this._map.size;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
get isEmpty(): boolean {
|
|
88
|
+
return this._map.isEmpty;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
get comparator(): Compare<T> {
|
|
92
|
+
return this._compare;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
get eq(): Eq<T> {
|
|
96
|
+
return this._eq;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// ========================================================================
|
|
100
|
+
// Membership operations
|
|
101
|
+
// ========================================================================
|
|
102
|
+
|
|
103
|
+
has(element: T): boolean {
|
|
104
|
+
return this._map.has(element);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
contains(element: T): boolean {
|
|
108
|
+
return this.has(element);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
containsAll(other: Iterable<T>): boolean {
|
|
112
|
+
for (const element of other) {
|
|
113
|
+
if (!this.has(element)) {
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return true;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// ========================================================================
|
|
121
|
+
// Modification operations
|
|
122
|
+
// ========================================================================
|
|
123
|
+
|
|
124
|
+
add(element: T): boolean {
|
|
125
|
+
const oldValue = this._map.set(element, PRESENT);
|
|
126
|
+
return oldValue === undefined; // Returns true if element was added (not already present)
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
remove(element: T): boolean {
|
|
130
|
+
const removed = this._map.delete(element);
|
|
131
|
+
return removed !== undefined;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
clear(): void {
|
|
135
|
+
this._map.clear();
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// ========================================================================
|
|
139
|
+
// Bulk operations
|
|
140
|
+
// ========================================================================
|
|
141
|
+
|
|
142
|
+
addAll(elements: Iterable<T>): boolean {
|
|
143
|
+
let modified = false;
|
|
144
|
+
for (const element of elements) {
|
|
145
|
+
if (this.add(element)) {
|
|
146
|
+
modified = true;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return modified;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
removeAll(elements: Iterable<T>): boolean {
|
|
153
|
+
let modified = false;
|
|
154
|
+
for (const element of elements) {
|
|
155
|
+
if (this.remove(element)) {
|
|
156
|
+
modified = true;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return modified;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
retainAll(elements: Iterable<T>): boolean {
|
|
163
|
+
const toRetain = new Set<T>();
|
|
164
|
+
for (const element of elements) {
|
|
165
|
+
toRetain.add(element);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
let modified = false;
|
|
169
|
+
for (const element of Array.from(this)) {
|
|
170
|
+
if (!toRetain.has(element)) {
|
|
171
|
+
this.remove(element);
|
|
172
|
+
modified = true;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
return modified;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// ========================================================================
|
|
179
|
+
// Set operations
|
|
180
|
+
// ========================================================================
|
|
181
|
+
|
|
182
|
+
union(other: Iterable<T>): TreeSet<T> {
|
|
183
|
+
const result = new TreeSet<T>({
|
|
184
|
+
compare: this._compare,
|
|
185
|
+
eq: this._eq,
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
for (const element of this) {
|
|
189
|
+
result.add(element);
|
|
190
|
+
}
|
|
191
|
+
for (const element of other) {
|
|
192
|
+
result.add(element);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return result;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
intersection(other: Iterable<T>): TreeSet<T> {
|
|
199
|
+
const result = new TreeSet<T>({
|
|
200
|
+
compare: this._compare,
|
|
201
|
+
eq: this._eq,
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
const otherSet = new Set<T>();
|
|
205
|
+
for (const element of other) {
|
|
206
|
+
otherSet.add(element);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
for (const element of this) {
|
|
210
|
+
if (otherSet.has(element)) {
|
|
211
|
+
result.add(element);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
return result;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
difference(other: Iterable<T>): TreeSet<T> {
|
|
219
|
+
const result = new TreeSet<T>({
|
|
220
|
+
compare: this._compare,
|
|
221
|
+
eq: this._eq,
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
const otherSet = new Set<T>();
|
|
225
|
+
for (const element of other) {
|
|
226
|
+
otherSet.add(element);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
for (const element of this) {
|
|
230
|
+
if (!otherSet.has(element)) {
|
|
231
|
+
result.add(element);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
return result;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
symmetricDifference(other: Iterable<T>): TreeSet<T> {
|
|
239
|
+
const result = new TreeSet<T>({
|
|
240
|
+
compare: this._compare,
|
|
241
|
+
eq: this._eq,
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
// Add all elements from this set
|
|
245
|
+
for (const element of this) {
|
|
246
|
+
result.add(element);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// Toggle elements from other set
|
|
250
|
+
for (const element of other) {
|
|
251
|
+
if (result.has(element)) {
|
|
252
|
+
result.remove(element);
|
|
253
|
+
} else {
|
|
254
|
+
result.add(element);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
return result;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
isSubsetOf(other: Iterable<T>): boolean {
|
|
262
|
+
const otherSet = new Set<T>();
|
|
263
|
+
for (const element of other) {
|
|
264
|
+
otherSet.add(element);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
for (const element of this) {
|
|
268
|
+
if (!otherSet.has(element)) {
|
|
269
|
+
return false;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
return true;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
isSupersetOf(other: Iterable<T>): boolean {
|
|
276
|
+
for (const element of other) {
|
|
277
|
+
if (!this.has(element)) {
|
|
278
|
+
return false;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
return true;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
isDisjointFrom(other: Iterable<T>): boolean {
|
|
285
|
+
for (const element of other) {
|
|
286
|
+
if (this.has(element)) {
|
|
287
|
+
return false;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
return true;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// ========================================================================
|
|
294
|
+
// SortedSet operations
|
|
295
|
+
// ========================================================================
|
|
296
|
+
|
|
297
|
+
first(): T {
|
|
298
|
+
const key = this._map.firstKey();
|
|
299
|
+
return key;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
last(): T {
|
|
303
|
+
const key = this._map.lastKey();
|
|
304
|
+
return key;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
headSet(toElement: T): SortedSet<T> {
|
|
308
|
+
const result = new TreeSet<T>({
|
|
309
|
+
compare: this._compare,
|
|
310
|
+
eq: this._eq,
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
for (const element of this) {
|
|
314
|
+
if (this._compare(element, toElement) < 0) {
|
|
315
|
+
result.add(element);
|
|
316
|
+
} else {
|
|
317
|
+
break; // Elements are sorted
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
return result;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
tailSet(fromElement: T): SortedSet<T> {
|
|
325
|
+
const result = new TreeSet<T>({
|
|
326
|
+
compare: this._compare,
|
|
327
|
+
eq: this._eq,
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
let started = false;
|
|
331
|
+
for (const element of this) {
|
|
332
|
+
if (!started && this._compare(element, fromElement) < 0) {
|
|
333
|
+
continue;
|
|
334
|
+
}
|
|
335
|
+
started = true;
|
|
336
|
+
result.add(element);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
return result;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
subSet(fromElement: T, toElement: T): SortedSet<T> {
|
|
343
|
+
const result = new TreeSet<T>({
|
|
344
|
+
compare: this._compare,
|
|
345
|
+
eq: this._eq,
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
for (const element of this) {
|
|
349
|
+
const cmpFrom = this._compare(element, fromElement);
|
|
350
|
+
const cmpTo = this._compare(element, toElement);
|
|
351
|
+
|
|
352
|
+
if (cmpFrom >= 0 && cmpTo < 0) {
|
|
353
|
+
result.add(element);
|
|
354
|
+
} else if (cmpTo >= 0) {
|
|
355
|
+
break; // Past the range
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
return result;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// ========================================================================
|
|
363
|
+
// NavigableSet operations
|
|
364
|
+
// ========================================================================
|
|
365
|
+
|
|
366
|
+
floor(element: T): T | undefined {
|
|
367
|
+
return this._map.floorKey(element);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
ceiling(element: T): T | undefined {
|
|
371
|
+
return this._map.ceilingKey(element);
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
lower(element: T): T | undefined {
|
|
375
|
+
return this._map.lowerKey(element);
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
higher(element: T): T | undefined {
|
|
379
|
+
return this._map.higherKey(element);
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
pollFirst(): T | undefined {
|
|
383
|
+
const entry = this._map.pollFirstEntry();
|
|
384
|
+
return entry?.key;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
pollLast(): T | undefined {
|
|
388
|
+
const entry = this._map.pollLastEntry();
|
|
389
|
+
return entry?.key;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
descendingSet(): NavigableSet<T> {
|
|
393
|
+
const reversed = new TreeSet<T>({
|
|
394
|
+
compare: (a, b) => this._compare(b, a),
|
|
395
|
+
eq: this._eq,
|
|
396
|
+
});
|
|
397
|
+
|
|
398
|
+
for (const element of this) {
|
|
399
|
+
reversed.add(element);
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
return reversed;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
*descendingIterator(): IterableIterator<T> {
|
|
406
|
+
yield* this._map.descendingKeys();
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
// ========================================================================
|
|
410
|
+
// View operations
|
|
411
|
+
// ========================================================================
|
|
412
|
+
|
|
413
|
+
*[Symbol.iterator](): Iterator<T> {
|
|
414
|
+
yield* this._map.keys();
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
forEach(action: (element: T, index: number) => void): void {
|
|
418
|
+
let index = 0;
|
|
419
|
+
for (const element of this) {
|
|
420
|
+
action(element, index++);
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
toArray(): T[] {
|
|
425
|
+
return Array.from(this);
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
// ========================================================================
|
|
429
|
+
// Utility methods
|
|
430
|
+
// ========================================================================
|
|
431
|
+
|
|
432
|
+
toString(): string {
|
|
433
|
+
const elements = Array.from(this).join(', ');
|
|
434
|
+
return `TreeSet{${elements}}`;
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
/**
|
|
439
|
+
* Factory function to create a TreeSet.
|
|
440
|
+
*
|
|
441
|
+
* @example
|
|
442
|
+
* const set = treeSet<string>()
|
|
443
|
+
* set.add('c')
|
|
444
|
+
* set.add('a')
|
|
445
|
+
* set.add('b')
|
|
446
|
+
* // Iteration order: a, b, c
|
|
447
|
+
*
|
|
448
|
+
* @example
|
|
449
|
+
* // With initial elements
|
|
450
|
+
* const set = treeSet(['c', 'a', 'b'])
|
|
451
|
+
* // Iteration order: a, b, c
|
|
452
|
+
*
|
|
453
|
+
* @example
|
|
454
|
+
* // Custom comparator for descending order
|
|
455
|
+
* const set = treeSet<number>({ compare: (a, b) => b - a })
|
|
456
|
+
*/
|
|
457
|
+
export function treeSet<T>(
|
|
458
|
+
optionsOrElements?: TreeSetOptions<T> | Iterable<T>
|
|
459
|
+
): TreeSet<T> {
|
|
460
|
+
if (optionsOrElements && Symbol.iterator in optionsOrElements) {
|
|
461
|
+
const set = new TreeSet<T>();
|
|
462
|
+
for (const element of optionsOrElements as Iterable<T>) {
|
|
463
|
+
set.add(element);
|
|
464
|
+
}
|
|
465
|
+
return set;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
return new TreeSet<T>(optionsOrElements as TreeSetOptions<T>);
|
|
469
|
+
}
|