list-toolkit 2.2.5 → 2.3.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/README.md +40 -36
- package/llms-full.txt +743 -0
- package/llms.txt +100 -0
- package/package.json +40 -32
- package/src/cache/cache-fifo.d.ts +6 -0
- package/src/cache/cache-fifo.js +7 -4
- package/src/cache/cache-lfu.d.ts +18 -0
- package/src/cache/cache-lfu.js +18 -6
- package/src/cache/cache-lru.d.ts +74 -0
- package/src/cache/cache-lru.js +60 -5
- package/src/cache/cache-random.d.ts +20 -0
- package/src/cache/cache-random.js +17 -6
- package/src/cache/decorator.d.ts +46 -0
- package/src/cache/decorator.js +26 -2
- package/src/cache.d.ts +13 -0
- package/src/cache.js +7 -2
- package/src/ext-list.d.ts +3 -0
- package/src/ext-list.js +0 -2
- package/src/ext-slist.d.ts +3 -0
- package/src/ext-slist.js +0 -2
- package/src/ext-value-list.d.ts +3 -0
- package/src/ext-value-list.js +0 -2
- package/src/ext-value-slist.d.ts +3 -0
- package/src/ext-value-slist.js +0 -2
- package/src/heap/basics.d.ts +89 -0
- package/src/heap/basics.js +42 -5
- package/src/heap/leftist-heap.d.ts +107 -0
- package/src/heap/leftist-heap.js +54 -2
- package/src/heap/min-heap.d.ts +270 -0
- package/src/heap/min-heap.js +186 -2
- package/src/heap/skew-heap.d.ts +105 -0
- package/src/heap/skew-heap.js +54 -2
- package/src/heap.d.ts +3 -0
- package/src/heap.js +0 -2
- package/src/list/basics.d.ts +43 -0
- package/src/list/basics.js +26 -8
- package/src/list/core.d.ts +271 -0
- package/src/list/core.js +162 -7
- package/src/list/ext-value.d.ts +253 -0
- package/src/list/ext-value.js +40 -6
- package/src/list/ext.d.ts +242 -0
- package/src/list/ext.js +148 -10
- package/src/list/nodes.d.ts +336 -0
- package/src/list/nodes.js +141 -3
- package/src/list/ptr.d.ts +72 -0
- package/src/list/ptr.js +44 -2
- package/src/list/value.d.ts +292 -0
- package/src/list/value.js +47 -6
- package/src/list-helpers.d.ts +44 -0
- package/src/list-helpers.js +36 -3
- package/src/list-utils.d.ts +141 -0
- package/src/list-utils.js +89 -3
- package/src/list.d.ts +3 -0
- package/src/list.js +0 -2
- package/src/meta-utils.d.ts +212 -0
- package/src/meta-utils.js +152 -1
- package/src/nt-utils.d.ts +91 -0
- package/src/nt-utils.js +65 -4
- package/src/queue.d.ts +74 -0
- package/src/queue.js +28 -2
- package/src/slist/basics.d.ts +47 -0
- package/src/slist/basics.js +23 -8
- package/src/slist/core.d.ts +251 -0
- package/src/slist/core.js +151 -6
- package/src/slist/ext-value.d.ts +188 -0
- package/src/slist/ext-value.js +35 -6
- package/src/slist/ext.d.ts +182 -0
- package/src/slist/ext.js +114 -12
- package/src/slist/nodes.d.ts +361 -0
- package/src/slist/nodes.js +156 -3
- package/src/slist/ptr.d.ts +73 -0
- package/src/slist/ptr.js +45 -2
- package/src/slist/value.d.ts +246 -0
- package/src/slist/value.js +38 -6
- package/src/slist.d.ts +3 -0
- package/src/slist.js +0 -2
- package/src/stack.d.ts +59 -0
- package/src/stack.js +29 -3
- package/src/tree/splay-tree.d.ts +151 -0
- package/src/tree/splay-tree.js +94 -3
- package/src/value-list.d.ts +3 -0
- package/src/value-list.js +0 -2
- package/src/value-slist.d.ts +3 -0
- package/src/value-slist.js +0 -2
- package/cjs/cache/cache-fifo.js +0 -37
- package/cjs/cache/cache-lfu.js +0 -76
- package/cjs/cache/cache-lru.js +0 -100
- package/cjs/cache/cache-random.js +0 -77
- package/cjs/cache/decorator.js +0 -47
- package/cjs/cache.js +0 -27
- package/cjs/ext-list.js +0 -21
- package/cjs/ext-slist.js +0 -21
- package/cjs/ext-value-list.js +0 -21
- package/cjs/ext-value-slist.js +0 -21
- package/cjs/heap/basics.js +0 -63
- package/cjs/heap/leftist-heap.js +0 -124
- package/cjs/heap/min-heap.js +0 -294
- package/cjs/heap/skew-heap.js +0 -114
- package/cjs/heap.js +0 -21
- package/cjs/list/basics.js +0 -88
- package/cjs/list/core.js +0 -305
- package/cjs/list/ext-value.js +0 -88
- package/cjs/list/ext.js +0 -356
- package/cjs/list/nodes.js +0 -240
- package/cjs/list/ptr.js +0 -61
- package/cjs/list/value.js +0 -99
- package/cjs/list-helpers.js +0 -91
- package/cjs/list-utils.js +0 -141
- package/cjs/list.js +0 -21
- package/cjs/meta-utils.js +0 -171
- package/cjs/nt-utils.js +0 -132
- package/cjs/package.json +0 -1
- package/cjs/queue.js +0 -58
- package/cjs/slist/basics.js +0 -71
- package/cjs/slist/core.js +0 -362
- package/cjs/slist/ext-value.js +0 -82
- package/cjs/slist/ext.js +0 -336
- package/cjs/slist/nodes.js +0 -276
- package/cjs/slist/ptr.js +0 -87
- package/cjs/slist/value.js +0 -90
- package/cjs/slist.js +0 -21
- package/cjs/stack.js +0 -55
- package/cjs/tree/splay-tree.js +0 -362
- package/cjs/value-list.js +0 -21
- package/cjs/value-slist.js +0 -21
package/src/list/core.js
CHANGED
|
@@ -1,61 +1,105 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
1
|
import {ExtListBase, HeadNode} from './nodes.js';
|
|
4
2
|
import {pop, splice, append} from './basics.js';
|
|
5
3
|
import Ptr from './ptr.js';
|
|
6
4
|
import {addAliases, mapIterator, normalizeIterator} from '../meta-utils.js';
|
|
7
5
|
|
|
6
|
+
/** Hosted node-based doubly linked list with a sentinel head. */
|
|
8
7
|
export class List extends HeadNode {
|
|
8
|
+
/** Pointer to the first node. */
|
|
9
9
|
get frontPtr() {
|
|
10
10
|
return new Ptr(this, this.front);
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
+
/** Pointer to the last node. */
|
|
13
14
|
get backPtr() {
|
|
14
15
|
return new Ptr(this, this.back);
|
|
15
16
|
}
|
|
16
17
|
|
|
18
|
+
/**
|
|
19
|
+
* Create a pointer to a node in this list.
|
|
20
|
+
* @param {object} [node] - Target node, or `undefined` for the front.
|
|
21
|
+
* @returns {Ptr} A new Ptr.
|
|
22
|
+
*/
|
|
17
23
|
makePtr(node) {
|
|
18
24
|
if (node && !this.isNodeLike(node)) throw new Error('"node" is not a compatible node');
|
|
19
25
|
return new Ptr(this, node || this.front);
|
|
20
26
|
}
|
|
21
27
|
|
|
28
|
+
/**
|
|
29
|
+
* Create a pointer to the node after `prev`.
|
|
30
|
+
* @param {object} [prev] - Preceding node, or `undefined` for the front.
|
|
31
|
+
* @returns {Ptr} A new Ptr.
|
|
32
|
+
*/
|
|
22
33
|
makePtrFromPrev(prev) {
|
|
23
34
|
if (prev && !this.isNodeLike(prev)) throw new Error('"prev" is not a compatible node');
|
|
24
35
|
return new Ptr(this, prev ? prev[this.nextName] : this.front);
|
|
25
36
|
}
|
|
26
37
|
|
|
38
|
+
/**
|
|
39
|
+
* Insert a value at the front.
|
|
40
|
+
* @param {*} value - Node or value to insert.
|
|
41
|
+
* @returns {Ptr} A Ptr to the front.
|
|
42
|
+
*/
|
|
27
43
|
pushFront(value) {
|
|
28
44
|
const node = this.adoptValue(value);
|
|
29
45
|
splice(this, this, node);
|
|
30
46
|
return this.makePtr(node);
|
|
31
47
|
}
|
|
32
48
|
|
|
49
|
+
/**
|
|
50
|
+
* Insert a value at the back.
|
|
51
|
+
* @param {*} value - Node or value to insert.
|
|
52
|
+
* @returns {Ptr} A Ptr to the inserted node.
|
|
53
|
+
*/
|
|
33
54
|
pushBack(value) {
|
|
34
55
|
const node = this.adoptValue(value);
|
|
35
56
|
splice(this, this[this.prevName], node);
|
|
36
57
|
return this.makePtr(node);
|
|
37
58
|
}
|
|
38
59
|
|
|
60
|
+
/**
|
|
61
|
+
* Remove and return the front node.
|
|
62
|
+
* @returns {object|undefined} The removed node, or `undefined` if empty.
|
|
63
|
+
*/
|
|
39
64
|
popFrontNode() {
|
|
40
65
|
if (!this.isEmpty) return pop(this, this[this.nextName]).extracted;
|
|
41
66
|
}
|
|
42
67
|
|
|
68
|
+
/**
|
|
69
|
+
* Remove and return the back node.
|
|
70
|
+
* @returns {object|undefined} The removed node, or `undefined` if empty.
|
|
71
|
+
*/
|
|
43
72
|
popBackNode() {
|
|
44
73
|
if (!this.isEmpty) return pop(this, this[this.prevName]).extracted;
|
|
45
74
|
}
|
|
46
75
|
|
|
76
|
+
/**
|
|
77
|
+
* Insert an existing node at the front.
|
|
78
|
+
* @param {object} nodeOrPtr - Node or pointer to insert.
|
|
79
|
+
* @returns {Ptr} A Ptr to the front.
|
|
80
|
+
*/
|
|
47
81
|
pushFrontNode(nodeOrPtr) {
|
|
48
82
|
const node = this.adoptNode(nodeOrPtr);
|
|
49
83
|
splice(this, this, node);
|
|
50
84
|
return this.makePtr(node);
|
|
51
85
|
}
|
|
52
86
|
|
|
87
|
+
/**
|
|
88
|
+
* Insert an existing node at the back.
|
|
89
|
+
* @param {object} nodeOrPtr - Node or pointer to insert.
|
|
90
|
+
* @returns {Ptr} A Ptr to the inserted node.
|
|
91
|
+
*/
|
|
53
92
|
pushBackNode(nodeOrPtr) {
|
|
54
93
|
const node = this.adoptNode(nodeOrPtr);
|
|
55
94
|
splice(this, this[this.prevName], node);
|
|
56
95
|
return this.makePtr(node);
|
|
57
96
|
}
|
|
58
97
|
|
|
98
|
+
/**
|
|
99
|
+
* Move all nodes from another list to the front.
|
|
100
|
+
* @param {HeadNode} list - Compatible list to consume.
|
|
101
|
+
* @returns {Ptr} A Ptr to the new front.
|
|
102
|
+
*/
|
|
59
103
|
appendFront(list) {
|
|
60
104
|
if (!this.isCompatible(list)) throw new Error('Incompatible lists');
|
|
61
105
|
if (list.isEmpty) return this;
|
|
@@ -66,6 +110,11 @@ export class List extends HeadNode {
|
|
|
66
110
|
return this.makePtr();
|
|
67
111
|
}
|
|
68
112
|
|
|
113
|
+
/**
|
|
114
|
+
* Move all nodes from another list to the back.
|
|
115
|
+
* @param {HeadNode} list - Compatible list to consume.
|
|
116
|
+
* @returns {Ptr} A Ptr to the first appended node.
|
|
117
|
+
*/
|
|
69
118
|
appendBack(list) {
|
|
70
119
|
if (!this.isCompatible(list)) throw new Error('Incompatible lists');
|
|
71
120
|
if (list.isEmpty) return this;
|
|
@@ -76,6 +125,11 @@ export class List extends HeadNode {
|
|
|
76
125
|
return this.makePtr(head);
|
|
77
126
|
}
|
|
78
127
|
|
|
128
|
+
/**
|
|
129
|
+
* Move a node to the front.
|
|
130
|
+
* @param {object} nodeOrPtr - Node or pointer to move.
|
|
131
|
+
* @returns {Ptr} A Ptr to the front.
|
|
132
|
+
*/
|
|
79
133
|
moveToFront(nodeOrPtr) {
|
|
80
134
|
const node = this.normalizeNode(nodeOrPtr);
|
|
81
135
|
if (this[this.nextName] !== node) {
|
|
@@ -84,6 +138,11 @@ export class List extends HeadNode {
|
|
|
84
138
|
return this.frontPtr;
|
|
85
139
|
}
|
|
86
140
|
|
|
141
|
+
/**
|
|
142
|
+
* Move a node to the back.
|
|
143
|
+
* @param {object} nodeOrPtr - Node or pointer to move.
|
|
144
|
+
* @returns {Ptr} A Ptr to the back.
|
|
145
|
+
*/
|
|
87
146
|
moveToBack(nodeOrPtr) {
|
|
88
147
|
const node = this.normalizeNode(nodeOrPtr);
|
|
89
148
|
if (this[this.prevName] !== node) {
|
|
@@ -92,6 +151,11 @@ export class List extends HeadNode {
|
|
|
92
151
|
return this.backPtr;
|
|
93
152
|
}
|
|
94
153
|
|
|
154
|
+
/**
|
|
155
|
+
* Remove all nodes.
|
|
156
|
+
* @param {boolean} [drop] - If `true`, make each removed node stand-alone.
|
|
157
|
+
* @returns {List} `this` for chaining.
|
|
158
|
+
*/
|
|
95
159
|
clear(drop) {
|
|
96
160
|
if (drop) {
|
|
97
161
|
while (!this.isEmpty) this.popFrontNode();
|
|
@@ -101,14 +165,30 @@ export class List extends HeadNode {
|
|
|
101
165
|
return this;
|
|
102
166
|
}
|
|
103
167
|
|
|
168
|
+
/**
|
|
169
|
+
* Remove a node from the list.
|
|
170
|
+
* @param {object} nodeOrPtr - Node or pointer to remove.
|
|
171
|
+
* @returns {object} The removed node.
|
|
172
|
+
*/
|
|
104
173
|
removeNode(nodeOrPtr) {
|
|
105
174
|
return pop(this, this.normalizeNode(nodeOrPtr)).extracted;
|
|
106
175
|
}
|
|
107
176
|
|
|
177
|
+
/**
|
|
178
|
+
* Remove a range and optionally drop nodes.
|
|
179
|
+
* @param {object} [range] - Range to remove.
|
|
180
|
+
* @param {boolean} [drop] - If `true`, make each removed node stand-alone.
|
|
181
|
+
* @returns {List} A new List containing the removed nodes.
|
|
182
|
+
*/
|
|
108
183
|
removeRange(range, drop) {
|
|
109
184
|
return this.extractRange(range).clear(drop);
|
|
110
185
|
}
|
|
111
186
|
|
|
187
|
+
/**
|
|
188
|
+
* Extract a range into a new list.
|
|
189
|
+
* @param {object} [range={}] - Range to extract (defaults to the whole list).
|
|
190
|
+
* @returns {List} A new List containing the extracted nodes.
|
|
191
|
+
*/
|
|
112
192
|
extractRange(range = {}) {
|
|
113
193
|
range = this.normalizeRange(range);
|
|
114
194
|
range.from ||= this.front;
|
|
@@ -116,11 +196,16 @@ export class List extends HeadNode {
|
|
|
116
196
|
return append(this, this.make(), range);
|
|
117
197
|
}
|
|
118
198
|
|
|
199
|
+
/**
|
|
200
|
+
* Extract nodes that satisfy a condition into a new list.
|
|
201
|
+
* @param {Function} condition - Predicate receiving each node.
|
|
202
|
+
* @returns {List} A new List containing the extracted nodes.
|
|
203
|
+
*/
|
|
119
204
|
extractBy(condition) {
|
|
120
205
|
const extracted = this.make();
|
|
121
206
|
if (this.isEmpty) return extracted;
|
|
122
207
|
|
|
123
|
-
while (this.isEmpty && condition(this.front)) extracted.pushBack(this.
|
|
208
|
+
while (!this.isEmpty && condition(this.front)) extracted.pushBack(this.popFrontNode());
|
|
124
209
|
if (this.isOneOrEmpty) return extracted;
|
|
125
210
|
|
|
126
211
|
for (const ptr of this.getPtrIterator({from: this.front[this.nextName]})) {
|
|
@@ -130,6 +215,10 @@ export class List extends HeadNode {
|
|
|
130
215
|
return extracted;
|
|
131
216
|
}
|
|
132
217
|
|
|
218
|
+
/**
|
|
219
|
+
* Reverse the order of all nodes in place.
|
|
220
|
+
* @returns {List} `this` for chaining.
|
|
221
|
+
*/
|
|
133
222
|
reverse() {
|
|
134
223
|
let current = this;
|
|
135
224
|
do {
|
|
@@ -141,6 +230,11 @@ export class List extends HeadNode {
|
|
|
141
230
|
return this;
|
|
142
231
|
}
|
|
143
232
|
|
|
233
|
+
/**
|
|
234
|
+
* Sort nodes in place using merge sort.
|
|
235
|
+
* @param {Function} lessFn - Returns `true` if `a` should precede `b`.
|
|
236
|
+
* @returns {List} `this` for chaining.
|
|
237
|
+
*/
|
|
144
238
|
sort(lessFn) {
|
|
145
239
|
if (this.isOneOrEmpty) return this;
|
|
146
240
|
|
|
@@ -167,10 +261,18 @@ export class List extends HeadNode {
|
|
|
167
261
|
return this;
|
|
168
262
|
}
|
|
169
263
|
|
|
264
|
+
/**
|
|
265
|
+
* Detach all nodes as a raw circular list.
|
|
266
|
+
* @returns {object|null} Head of the raw circular list, or `null` if empty.
|
|
267
|
+
*/
|
|
170
268
|
releaseRawList() {
|
|
171
269
|
return this.isEmpty ? null : pop(this, this).rest;
|
|
172
270
|
}
|
|
173
271
|
|
|
272
|
+
/**
|
|
273
|
+
* Detach all nodes as a null-terminated list.
|
|
274
|
+
* @returns {{head: object, tail: object}|null} Object with `head` and `tail`, or `null` if empty.
|
|
275
|
+
*/
|
|
174
276
|
releaseNTList() {
|
|
175
277
|
if (this.isEmpty) return null;
|
|
176
278
|
const head = this[this.nextName],
|
|
@@ -180,6 +282,11 @@ export class List extends HeadNode {
|
|
|
180
282
|
return {head, tail};
|
|
181
283
|
}
|
|
182
284
|
|
|
285
|
+
/**
|
|
286
|
+
* Validate that a range is reachable within this list.
|
|
287
|
+
* @param {object} [range={}] - Range to validate.
|
|
288
|
+
* @returns {boolean} `true` if the range is valid.
|
|
289
|
+
*/
|
|
183
290
|
validateRange(range = {}) {
|
|
184
291
|
range = this.normalizeRange(range);
|
|
185
292
|
let current = range.from;
|
|
@@ -190,8 +297,7 @@ export class List extends HeadNode {
|
|
|
190
297
|
return true;
|
|
191
298
|
}
|
|
192
299
|
|
|
193
|
-
|
|
194
|
-
|
|
300
|
+
/** Iterate over nodes from front to back. */
|
|
195
301
|
[Symbol.iterator]() {
|
|
196
302
|
let current = this[this.nextName],
|
|
197
303
|
readyToStop = this.isEmpty;
|
|
@@ -206,6 +312,11 @@ export class List extends HeadNode {
|
|
|
206
312
|
});
|
|
207
313
|
}
|
|
208
314
|
|
|
315
|
+
/**
|
|
316
|
+
* Get an iterable over nodes in a range.
|
|
317
|
+
* @param {object} [range={}] - Sub-range to iterate.
|
|
318
|
+
* @returns {Iterable} An iterable iterator of nodes.
|
|
319
|
+
*/
|
|
209
320
|
getNodeIterator(range = {}) {
|
|
210
321
|
range = this.normalizeRange(range);
|
|
211
322
|
const {from, to} = range;
|
|
@@ -227,10 +338,20 @@ export class List extends HeadNode {
|
|
|
227
338
|
};
|
|
228
339
|
}
|
|
229
340
|
|
|
341
|
+
/**
|
|
342
|
+
* Get an iterable of Ptr objects over a range.
|
|
343
|
+
* @param {object} [range] - Sub-range to iterate.
|
|
344
|
+
* @returns {Iterable} An iterable iterator of Ptrs.
|
|
345
|
+
*/
|
|
230
346
|
getPtrIterator(range) {
|
|
231
347
|
return mapIterator(this.getNodeIterator(range), node => new Ptr(this, node));
|
|
232
348
|
}
|
|
233
349
|
|
|
350
|
+
/**
|
|
351
|
+
* Get an iterable over nodes in reverse order.
|
|
352
|
+
* @param {object} [range={}] - Sub-range to iterate.
|
|
353
|
+
* @returns {Iterable} An iterable iterator of nodes.
|
|
354
|
+
*/
|
|
234
355
|
getReverseNodeIterator(range = {}) {
|
|
235
356
|
range = this.normalizeRange(range);
|
|
236
357
|
const {from, to} = range;
|
|
@@ -252,30 +373,59 @@ export class List extends HeadNode {
|
|
|
252
373
|
};
|
|
253
374
|
}
|
|
254
375
|
|
|
376
|
+
/**
|
|
377
|
+
* Get an iterable of Ptr objects in reverse order.
|
|
378
|
+
* @param {object} [range] - Sub-range to iterate.
|
|
379
|
+
* @returns {Iterable} An iterable iterator of Ptrs.
|
|
380
|
+
*/
|
|
255
381
|
getReversePtrIterator(range) {
|
|
256
382
|
return mapIterator(this.getReverseNodeIterator(range), node => new Ptr(this, node));
|
|
257
383
|
}
|
|
258
384
|
|
|
259
|
-
|
|
260
|
-
|
|
385
|
+
/**
|
|
386
|
+
* Create an empty list with the same options.
|
|
387
|
+
* @returns {List} A new empty List.
|
|
388
|
+
*/
|
|
261
389
|
make() {
|
|
262
390
|
return new List(this);
|
|
263
391
|
}
|
|
264
392
|
|
|
393
|
+
/**
|
|
394
|
+
* Create a list from values with the same options.
|
|
395
|
+
* @param {Iterable} values - Iterable of node objects.
|
|
396
|
+
* @returns {List} A new List.
|
|
397
|
+
*/
|
|
265
398
|
makeFrom(values) {
|
|
266
399
|
return List.from(values, this);
|
|
267
400
|
}
|
|
268
401
|
|
|
402
|
+
/**
|
|
403
|
+
* Create a list from a range with the same options.
|
|
404
|
+
* @param {object} range - Range to copy.
|
|
405
|
+
* @returns {List} A new List.
|
|
406
|
+
*/
|
|
269
407
|
makeFromRange(range) {
|
|
270
408
|
return List.fromRange(range, this);
|
|
271
409
|
}
|
|
272
410
|
|
|
411
|
+
/**
|
|
412
|
+
* Build a List from an iterable of node objects.
|
|
413
|
+
* @param {Iterable} values - Iterable of nodes.
|
|
414
|
+
* @param {object} [options] - Link property names.
|
|
415
|
+
* @returns {List} A new List.
|
|
416
|
+
*/
|
|
273
417
|
static from(values, options) {
|
|
274
418
|
const list = new List(options);
|
|
275
419
|
for (const value of values) list.pushBack(value);
|
|
276
420
|
return list;
|
|
277
421
|
}
|
|
278
422
|
|
|
423
|
+
/**
|
|
424
|
+
* Build a List from a range.
|
|
425
|
+
* @param {object} range - Range to copy.
|
|
426
|
+
* @param {object} [options] - Link property names.
|
|
427
|
+
* @returns {List} A new List.
|
|
428
|
+
*/
|
|
279
429
|
static fromRange(range, options) {
|
|
280
430
|
const list = new List(options);
|
|
281
431
|
if (!range) return list;
|
|
@@ -286,6 +436,11 @@ export class List extends HeadNode {
|
|
|
286
436
|
return append(list, list, range);
|
|
287
437
|
}
|
|
288
438
|
|
|
439
|
+
/**
|
|
440
|
+
* Build a List from an external list, consuming it.
|
|
441
|
+
* @param {ExtListBase} extList - External list to consume.
|
|
442
|
+
* @returns {List} A new List.
|
|
443
|
+
*/
|
|
289
444
|
static fromExtList(extList) {
|
|
290
445
|
if (!(extList instanceof ExtListBase)) throw new Error('Not a circular list');
|
|
291
446
|
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
import {ExtListBase, ValueNode, PtrBase, DllOptions, DllRange} from './nodes.js';
|
|
2
|
+
import {Ptr} from './ext.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* External (headless) value-based doubly linked list. Wraps values in {@link ValueNode}.
|
|
6
|
+
*
|
|
7
|
+
* Extends `ExtList` at runtime. Internally nodes are `ValueNode<V>`.
|
|
8
|
+
* The default iterator and `getIterator`/`getReverseIterator` yield
|
|
9
|
+
* unwrapped `V` values; use `getNodeIterator`/`getReverseNodeIterator`
|
|
10
|
+
* for `ValueNode<V>` nodes.
|
|
11
|
+
*/
|
|
12
|
+
export class ExtValueList<V = unknown> extends ExtListBase<ValueNode<V>> {
|
|
13
|
+
/**
|
|
14
|
+
* Create a pointer to a node in this list.
|
|
15
|
+
* @param node - Target node, or `undefined` for the head.
|
|
16
|
+
* @returns A new Ptr, or `null` if the list is empty and no node given.
|
|
17
|
+
*/
|
|
18
|
+
makePtr(node?: ValueNode<V>): Ptr<ValueNode<V>> | null;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Create a pointer to the node after `prev`.
|
|
22
|
+
* @param prev - Preceding node, or `undefined` for the front.
|
|
23
|
+
* @returns A new Ptr.
|
|
24
|
+
*/
|
|
25
|
+
makePtrFromPrev(prev?: ValueNode<V>): Ptr<ValueNode<V>>;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Remove the current head node and advance to the next.
|
|
29
|
+
* @returns The removed node, or `null` if empty.
|
|
30
|
+
*/
|
|
31
|
+
removeCurrent(): ValueNode<V> | null;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Remove the node before the head.
|
|
35
|
+
* @returns The removed node, or `null` if empty.
|
|
36
|
+
*/
|
|
37
|
+
removeNodeBefore(): ValueNode<V> | null;
|
|
38
|
+
|
|
39
|
+
/** Alias for {@link removeNodeBefore}. */
|
|
40
|
+
removeBefore(): ValueNode<V> | null;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Remove the node after the head.
|
|
44
|
+
* @returns The removed node, or `null` if empty.
|
|
45
|
+
*/
|
|
46
|
+
removeNodeAfter(): ValueNode<V> | null;
|
|
47
|
+
|
|
48
|
+
/** Alias for {@link removeNodeAfter}. */
|
|
49
|
+
removeAfter(): ValueNode<V> | null;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Adopt a value, pointer, or ValueNode into this list.
|
|
53
|
+
* @param value - Raw value, Ptr, or ValueNode.
|
|
54
|
+
* @returns A ValueNode ready for insertion.
|
|
55
|
+
*/
|
|
56
|
+
adoptValue(value: V | ValueNode<V> | PtrBase<ValueNode<V>>): ValueNode<V>;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Insert a value after the head.
|
|
60
|
+
* @param value - Raw value, ValueNode, or Ptr.
|
|
61
|
+
* @returns A Ptr to the inserted node.
|
|
62
|
+
*/
|
|
63
|
+
addAfter(value: V | ValueNode<V> | PtrBase<ValueNode<V>>): Ptr<ValueNode<V>>;
|
|
64
|
+
|
|
65
|
+
/** Alias for {@link addAfter}. */
|
|
66
|
+
add(value: V | ValueNode<V> | PtrBase<ValueNode<V>>): Ptr<ValueNode<V>>;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Insert a value before the head.
|
|
70
|
+
* @param value - Raw value, ValueNode, or Ptr.
|
|
71
|
+
* @returns A Ptr to the inserted node.
|
|
72
|
+
*/
|
|
73
|
+
addBefore(value: V | ValueNode<V> | PtrBase<ValueNode<V>>): Ptr<ValueNode<V>>;
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Insert an existing node before the head.
|
|
77
|
+
* @param nodeOrPtr - ValueNode or pointer to insert.
|
|
78
|
+
* @returns A Ptr to the inserted node.
|
|
79
|
+
*/
|
|
80
|
+
addNodeBefore(nodeOrPtr: ValueNode<V> | PtrBase<ValueNode<V>>): Ptr<ValueNode<V>>;
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Insert an existing node after the head.
|
|
84
|
+
* @param nodeOrPtr - ValueNode or pointer to insert.
|
|
85
|
+
* @returns A Ptr to the inserted node.
|
|
86
|
+
*/
|
|
87
|
+
addNodeAfter(nodeOrPtr: ValueNode<V> | PtrBase<ValueNode<V>>): Ptr<ValueNode<V>>;
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Splice another list's nodes before the head.
|
|
91
|
+
* @param extList - Compatible external list to consume.
|
|
92
|
+
* @returns A Ptr to the first inserted node, or `null` if empty.
|
|
93
|
+
*/
|
|
94
|
+
insertBefore(extList: ExtValueList<V>): Ptr<ValueNode<V>> | null;
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Splice another list's nodes after the head.
|
|
98
|
+
* @param extList - Compatible external list to consume.
|
|
99
|
+
* @returns A Ptr to the first inserted node, or `null` if empty.
|
|
100
|
+
*/
|
|
101
|
+
insertAfter(extList: ExtValueList<V>): Ptr<ValueNode<V>> | null;
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Move a node to just before the head.
|
|
105
|
+
* @param nodeOrPtr - Node or pointer to move.
|
|
106
|
+
* @returns A Ptr to the moved node, or `this` if already at head.
|
|
107
|
+
*/
|
|
108
|
+
moveBefore(nodeOrPtr: ValueNode<V> | PtrBase<ValueNode<V>>): Ptr<ValueNode<V>> | this;
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Move a node to just after the head.
|
|
112
|
+
* @param nodeOrPtr - Node or pointer to move.
|
|
113
|
+
* @returns A Ptr to the moved node, or `this` if already at head.
|
|
114
|
+
*/
|
|
115
|
+
moveAfter(nodeOrPtr: ValueNode<V> | PtrBase<ValueNode<V>>): Ptr<ValueNode<V>> | this;
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Remove all nodes.
|
|
119
|
+
* @param drop - If `true`, make each removed node stand-alone.
|
|
120
|
+
* @returns `this` for chaining.
|
|
121
|
+
*/
|
|
122
|
+
clear(drop?: boolean): this;
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Remove a single node from the list.
|
|
126
|
+
* @param nodeOrPtr - Node or pointer to remove.
|
|
127
|
+
* @returns The removed node, or `null` if empty.
|
|
128
|
+
*/
|
|
129
|
+
removeNode(nodeOrPtr: ValueNode<V> | PtrBase<ValueNode<V>>): ValueNode<V> | null;
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Remove a range of nodes and optionally drop them.
|
|
133
|
+
* @param range - Range to remove.
|
|
134
|
+
* @param drop - If `true`, make each removed node stand-alone.
|
|
135
|
+
* @returns A new ExtValueList containing the removed values.
|
|
136
|
+
*/
|
|
137
|
+
removeRange(range?: DllRange<ValueNode<V>>, drop?: boolean): ExtValueList<V>;
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Extract a range of nodes into a new list.
|
|
141
|
+
* @param range - Range to extract (defaults to the whole list).
|
|
142
|
+
* @returns A new ExtValueList containing the extracted values.
|
|
143
|
+
*/
|
|
144
|
+
extractRange(range?: DllRange<ValueNode<V>>): ExtValueList<V>;
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Extract nodes that satisfy a condition into a new list.
|
|
148
|
+
* @param condition - Predicate receiving each ValueNode.
|
|
149
|
+
* @returns A new ExtValueList containing the extracted values.
|
|
150
|
+
*/
|
|
151
|
+
extractBy(condition: (node: ValueNode<V>) => boolean): ExtValueList<V>;
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Reverse the order of all nodes in place.
|
|
155
|
+
* @returns `this` for chaining.
|
|
156
|
+
*/
|
|
157
|
+
reverse(): this;
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Sort nodes in place using merge sort.
|
|
161
|
+
* @param lessFn - Comparison receiving ValueNodes, returns `true` if `a` should precede `b`.
|
|
162
|
+
* @returns `this` for chaining.
|
|
163
|
+
*/
|
|
164
|
+
sort(lessFn: (a: ValueNode<V>, b: ValueNode<V>) => boolean): this;
|
|
165
|
+
|
|
166
|
+
/** Iterate over unwrapped values starting from the head. */
|
|
167
|
+
[Symbol.iterator](): IterableIterator<V>;
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Get an iterable over ValueNodes in a range.
|
|
171
|
+
* @param range - Sub-range to iterate.
|
|
172
|
+
* @returns An iterable iterator of ValueNodes.
|
|
173
|
+
*/
|
|
174
|
+
getNodeIterator(range?: DllRange<ValueNode<V>>): IterableIterator<ValueNode<V>>;
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Get an iterable over unwrapped values in a range.
|
|
178
|
+
* @param range - Sub-range to iterate.
|
|
179
|
+
* @returns An iterable iterator of values.
|
|
180
|
+
*/
|
|
181
|
+
getValueIterator(range?: DllRange<ValueNode<V>>): IterableIterator<V>;
|
|
182
|
+
|
|
183
|
+
/** Alias for {@link getValueIterator}. */
|
|
184
|
+
getIterator(range?: DllRange<ValueNode<V>>): IterableIterator<V>;
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Get an iterable over ValueNodes in reverse order.
|
|
188
|
+
* @param range - Sub-range to iterate.
|
|
189
|
+
* @returns An iterable iterator of ValueNodes.
|
|
190
|
+
*/
|
|
191
|
+
getReverseNodeIterator(range?: DllRange<ValueNode<V>>): IterableIterator<ValueNode<V>>;
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Get an iterable over unwrapped values in reverse order.
|
|
195
|
+
* @param range - Sub-range to iterate.
|
|
196
|
+
* @returns An iterable iterator of values.
|
|
197
|
+
*/
|
|
198
|
+
getReverseValueIterator(range?: DllRange<ValueNode<V>>): IterableIterator<V>;
|
|
199
|
+
|
|
200
|
+
/** Alias for {@link getReverseValueIterator}. */
|
|
201
|
+
getReverseIterator(range?: DllRange<ValueNode<V>>): IterableIterator<V>;
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Get an iterable of Ptr objects over a range.
|
|
205
|
+
* @param range - Sub-range to iterate.
|
|
206
|
+
* @returns An iterable iterator of Ptrs.
|
|
207
|
+
*/
|
|
208
|
+
getPtrIterator(range?: DllRange<ValueNode<V>>): IterableIterator<Ptr<ValueNode<V>>>;
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Get an iterable of Ptr objects in reverse order.
|
|
212
|
+
* @param range - Sub-range to iterate.
|
|
213
|
+
* @returns An iterable iterator of Ptrs.
|
|
214
|
+
*/
|
|
215
|
+
getReversePtrIterator(range?: DllRange<ValueNode<V>>): IterableIterator<Ptr<ValueNode<V>>>;
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Create a shallow clone of this list.
|
|
219
|
+
* @returns A new ExtValueList pointing to the same head.
|
|
220
|
+
*/
|
|
221
|
+
clone(): ExtValueList<V>;
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Create an empty list with the same options.
|
|
225
|
+
* @param head - Optional initial head node.
|
|
226
|
+
* @returns A new ExtValueList.
|
|
227
|
+
*/
|
|
228
|
+
make(head?: ValueNode<V> | null): ExtValueList<V>;
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Create a list from values with the same options.
|
|
232
|
+
* @param values - Iterable of values.
|
|
233
|
+
* @returns A new ExtValueList.
|
|
234
|
+
*/
|
|
235
|
+
makeFrom(values: Iterable<V>): ExtValueList<V>;
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Build an ExtValueList from an iterable.
|
|
239
|
+
* @param values - Iterable of values.
|
|
240
|
+
* @param options - Link property names.
|
|
241
|
+
* @returns A new ExtValueList.
|
|
242
|
+
*/
|
|
243
|
+
static from<V = unknown>(values: Iterable<V>, options?: DllOptions): ExtValueList<V>;
|
|
244
|
+
|
|
245
|
+
/** The Ptr class associated with this list type. */
|
|
246
|
+
static Ptr: typeof Ptr;
|
|
247
|
+
|
|
248
|
+
/** The ValueNode class used by this list type. */
|
|
249
|
+
static ValueNode: typeof ValueNode;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
export {ValueNode};
|
|
253
|
+
export default ExtValueList;
|
package/src/list/ext-value.js
CHANGED
|
@@ -1,10 +1,17 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
1
|
import ExtList, {Ptr} from './ext.js';
|
|
4
2
|
import {ValueNode} from './nodes.js';
|
|
5
3
|
import {addAliases, mapIterator, normalizeIterator} from '../meta-utils.js';
|
|
6
4
|
|
|
5
|
+
/**
|
|
6
|
+
* External (headless) value-based doubly linked list. Wraps values in {@link ValueNode}.
|
|
7
|
+
* Iterators yield unwrapped values; use `getNodeIterator` for ValueNode access.
|
|
8
|
+
*/
|
|
7
9
|
export class ExtValueList extends ExtList {
|
|
10
|
+
/**
|
|
11
|
+
* Adopt a value, pointer, or ValueNode into this list.
|
|
12
|
+
* @param {*} value - Raw value, Ptr, or ValueNode.
|
|
13
|
+
* @returns {ValueNode} A ValueNode ready for insertion.
|
|
14
|
+
*/
|
|
8
15
|
adoptValue(value) {
|
|
9
16
|
if (value instanceof Ptr) {
|
|
10
17
|
if (!this.isCompatiblePtr(value)) throw new Error('Incompatible pointer');
|
|
@@ -21,8 +28,7 @@ export class ExtValueList extends ExtList {
|
|
|
21
28
|
return new ValueNode(value, this);
|
|
22
29
|
}
|
|
23
30
|
|
|
24
|
-
|
|
25
|
-
|
|
31
|
+
/** Iterate over unwrapped values starting from the head. */
|
|
26
32
|
[Symbol.iterator]() {
|
|
27
33
|
let current = this.head,
|
|
28
34
|
readyToStop = this.isEmpty;
|
|
@@ -37,28 +43,56 @@ export class ExtValueList extends ExtList {
|
|
|
37
43
|
});
|
|
38
44
|
}
|
|
39
45
|
|
|
46
|
+
/**
|
|
47
|
+
* Get an iterable over unwrapped values in a range.
|
|
48
|
+
* @param {object} [range] - Sub-range to iterate.
|
|
49
|
+
* @returns {Iterable} An iterable iterator of values.
|
|
50
|
+
*/
|
|
40
51
|
getValueIterator(range) {
|
|
41
52
|
return mapIterator(this.getNodeIterator(range), node => node.value);
|
|
42
53
|
}
|
|
43
54
|
|
|
55
|
+
/**
|
|
56
|
+
* Get an iterable over unwrapped values in reverse order.
|
|
57
|
+
* @param {object} [range] - Sub-range to iterate.
|
|
58
|
+
* @returns {Iterable} An iterable iterator of values.
|
|
59
|
+
*/
|
|
44
60
|
getReverseValueIterator(range) {
|
|
45
61
|
return mapIterator(this.getReverseNodeIterator(range), node => node.value);
|
|
46
62
|
}
|
|
47
63
|
|
|
48
|
-
|
|
49
|
-
|
|
64
|
+
/**
|
|
65
|
+
* Create a shallow clone of this list.
|
|
66
|
+
* @returns {ExtValueList} A new ExtValueList pointing to the same head.
|
|
67
|
+
*/
|
|
50
68
|
clone() {
|
|
51
69
|
return new ExtValueList(this);
|
|
52
70
|
}
|
|
53
71
|
|
|
72
|
+
/**
|
|
73
|
+
* Create an empty list with the same options.
|
|
74
|
+
* @param {object|null} [head=null] - Optional initial head node.
|
|
75
|
+
* @returns {ExtValueList} A new ExtValueList.
|
|
76
|
+
*/
|
|
54
77
|
make(head = null) {
|
|
55
78
|
return new ExtValueList(head, this);
|
|
56
79
|
}
|
|
57
80
|
|
|
81
|
+
/**
|
|
82
|
+
* Create a list from values with the same options.
|
|
83
|
+
* @param {Iterable} values - Iterable of values.
|
|
84
|
+
* @returns {ExtValueList} A new ExtValueList.
|
|
85
|
+
*/
|
|
58
86
|
makeFrom(values) {
|
|
59
87
|
return ExtValueList.from(values, this);
|
|
60
88
|
}
|
|
61
89
|
|
|
90
|
+
/**
|
|
91
|
+
* Build an ExtValueList from an iterable.
|
|
92
|
+
* @param {Iterable} values - Iterable of values.
|
|
93
|
+
* @param {object} [options] - Link property names.
|
|
94
|
+
* @returns {ExtValueList} A new ExtValueList.
|
|
95
|
+
*/
|
|
62
96
|
static from(values, options) {
|
|
63
97
|
const list = new ExtValueList(null, options);
|
|
64
98
|
for (const value of values) {
|