list-toolkit 1.0.1
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/LICENSE +11 -0
- package/README.md +465 -0
- package/cjs/Cache.js +70 -0
- package/cjs/List.js +291 -0
- package/cjs/ListHead.js +308 -0
- package/cjs/MinHeap.js +261 -0
- package/cjs/SList.js +336 -0
- package/cjs/SListHead.js +363 -0
- package/cjs/package.json +1 -0
- package/cjs/utils.js +43 -0
- package/package.json +60 -0
- package/src/Cache.js +61 -0
- package/src/List.js +303 -0
- package/src/ListHead.js +304 -0
- package/src/MinHeap.js +283 -0
- package/src/SList.js +329 -0
- package/src/SListHead.js +353 -0
- package/src/utils.js +35 -0
package/cjs/SListHead.js
ADDED
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
var _utils = require("./utils.js");
|
|
8
|
+
class SListHead {
|
|
9
|
+
constructor(head = null, options) {
|
|
10
|
+
if (head instanceof SListHead) {
|
|
11
|
+
({
|
|
12
|
+
nextName: this.nextName,
|
|
13
|
+
head: this.head
|
|
14
|
+
} = head);
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
(0, _utils.copyOptions)(this, SListHead.defaults, options);
|
|
18
|
+
if (head instanceof SListHead.Unsafe) {
|
|
19
|
+
this.head = head.head;
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
if (head) {
|
|
23
|
+
if (!head[this.nextName]) {
|
|
24
|
+
this.adopt(head);
|
|
25
|
+
}
|
|
26
|
+
} else {
|
|
27
|
+
head = this.makeNode();
|
|
28
|
+
}
|
|
29
|
+
this.head = head;
|
|
30
|
+
}
|
|
31
|
+
get isEmpty() {
|
|
32
|
+
return this.head[this.nextName] === this.head;
|
|
33
|
+
}
|
|
34
|
+
get front() {
|
|
35
|
+
return this.head[this.nextName];
|
|
36
|
+
}
|
|
37
|
+
getBack() {
|
|
38
|
+
return SListHead.getPrev(this, this.head);
|
|
39
|
+
}
|
|
40
|
+
getLength() {
|
|
41
|
+
let n = 0;
|
|
42
|
+
for (let p = this.head[this.nextName]; p !== this.head; ++n, p = p[this.nextName]);
|
|
43
|
+
return n;
|
|
44
|
+
}
|
|
45
|
+
getPtr() {
|
|
46
|
+
return new SListHead.SListPtr(this);
|
|
47
|
+
}
|
|
48
|
+
popFront() {
|
|
49
|
+
if (this.head[this.nextName] !== this.head) {
|
|
50
|
+
return SListHead.pop(this, this.head).node;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
popBack() {
|
|
54
|
+
if (this.head[this.nextName] !== this.head) {
|
|
55
|
+
const prevLast = SListHead.getPrevPrev(this, this.head);
|
|
56
|
+
return SListHead.pop(this, prevLast).node;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
pushFront(node) {
|
|
60
|
+
this.adopt(node);
|
|
61
|
+
SListHead.splice(this, this.head, {
|
|
62
|
+
prev: node,
|
|
63
|
+
node
|
|
64
|
+
});
|
|
65
|
+
return this;
|
|
66
|
+
}
|
|
67
|
+
pushBack(node) {
|
|
68
|
+
this.adopt(node);
|
|
69
|
+
const last = SListHead.getPrev(this, this.head);
|
|
70
|
+
SListHead.splice(this, last, {
|
|
71
|
+
prev: node,
|
|
72
|
+
node
|
|
73
|
+
});
|
|
74
|
+
return this;
|
|
75
|
+
}
|
|
76
|
+
appendFront(list) {
|
|
77
|
+
let prevFrom, nodeTo;
|
|
78
|
+
if (list instanceof SListHead) {
|
|
79
|
+
if (list.head[this.nextName] === list.head) return this;
|
|
80
|
+
prevFrom = list.head;
|
|
81
|
+
nodeTo = SListHead.getPrev(this, list.head);
|
|
82
|
+
} else {
|
|
83
|
+
if (list[this.nextName] === list) return this;
|
|
84
|
+
prevFrom = nodeTo = SListHead.getPrev(this, list);
|
|
85
|
+
}
|
|
86
|
+
SListHead.splice(this, this.head, SListHead.extract(this, prevFrom, nodeTo));
|
|
87
|
+
return this;
|
|
88
|
+
}
|
|
89
|
+
appendBack(list) {
|
|
90
|
+
let prevFrom, nodeTo;
|
|
91
|
+
if (list instanceof SListHead) {
|
|
92
|
+
if (list.head[this.nextName] === list.head) return this;
|
|
93
|
+
prevFrom = list.head;
|
|
94
|
+
nodeTo = SListHead.getPrev(this, list.head);
|
|
95
|
+
} else {
|
|
96
|
+
if (list[this.nextName] === list) return this;
|
|
97
|
+
prevFrom = nodeTo = SListHead.getPrev(this, list);
|
|
98
|
+
}
|
|
99
|
+
const last = SListHead.getPrev(this, this.head);
|
|
100
|
+
SListHead.splice(this, last, SListHead.extract(this, prevFrom, nodeTo));
|
|
101
|
+
return this;
|
|
102
|
+
}
|
|
103
|
+
moveToFront(node) {
|
|
104
|
+
let prev;
|
|
105
|
+
if (node instanceof SListHead.SListPtr) {
|
|
106
|
+
prev = node.prev;
|
|
107
|
+
node = node.node;
|
|
108
|
+
if (this.head[this.nextName] === node) return this;
|
|
109
|
+
} else {
|
|
110
|
+
if (this.head[this.nextName] === node) return this;
|
|
111
|
+
prev = SListHead.getPrev(this, this.head, node);
|
|
112
|
+
}
|
|
113
|
+
SListHead.splice(this, this.head, SListHead.extract(this, prev, node));
|
|
114
|
+
return this;
|
|
115
|
+
}
|
|
116
|
+
moveToBack(node) {
|
|
117
|
+
let prev;
|
|
118
|
+
if (node instanceof SListHead.SListPtr) {
|
|
119
|
+
prev = node.prev;
|
|
120
|
+
node = node.node;
|
|
121
|
+
} else {
|
|
122
|
+
prev = SListHead.getPrev(this, this.head, node);
|
|
123
|
+
}
|
|
124
|
+
const last = SListHead.getPrev(this, this.head);
|
|
125
|
+
SListHead.splice(this, last, SListHead.extract(this, prev, node));
|
|
126
|
+
return this;
|
|
127
|
+
}
|
|
128
|
+
clear(drop) {
|
|
129
|
+
if (drop) {
|
|
130
|
+
while (!this.isEmpty) this.popFront();
|
|
131
|
+
} else {
|
|
132
|
+
this.head[this.nextName] = this.head;
|
|
133
|
+
}
|
|
134
|
+
return this;
|
|
135
|
+
}
|
|
136
|
+
remove(from, to = from) {
|
|
137
|
+
const prevFrom = from instanceof SListHead.SListPtr ? from.prev : SListHead.getPrev(this, this.head, from),
|
|
138
|
+
nodeTo = to instanceof SListHead.SListPtr ? to.node : to;
|
|
139
|
+
SListHead.extract(this, prevFrom, nodeTo);
|
|
140
|
+
return this;
|
|
141
|
+
}
|
|
142
|
+
extract(from, to) {
|
|
143
|
+
const prevFrom = from instanceof SListHead.SListPtr ? from.prev : SListHead.getPrev(this, this.head, from),
|
|
144
|
+
nodeTo = to instanceof SListHead.SListPtr ? to.node : to;
|
|
145
|
+
return this.make(SListHead.splice(this, this.makeNode(), SListHead.extract(this, prevFrom, nodeTo)));
|
|
146
|
+
}
|
|
147
|
+
reverse() {
|
|
148
|
+
let prev = this.head,
|
|
149
|
+
current = prev[this.nextName];
|
|
150
|
+
while (current !== this.head) {
|
|
151
|
+
const next = current[this.nextName];
|
|
152
|
+
current[this.nextName] = prev;
|
|
153
|
+
prev = current;
|
|
154
|
+
current = next;
|
|
155
|
+
}
|
|
156
|
+
this.head[this.nextName] = prev;
|
|
157
|
+
return this;
|
|
158
|
+
}
|
|
159
|
+
sort(compareFn) {
|
|
160
|
+
let prev = this.head;
|
|
161
|
+
for (const node of Array.from(this).sort(compareFn)) {
|
|
162
|
+
prev = prev[this.nextName] = node;
|
|
163
|
+
}
|
|
164
|
+
prev[this.nextName] = this.head;
|
|
165
|
+
return this;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// iterators
|
|
169
|
+
|
|
170
|
+
[Symbol.iterator]() {
|
|
171
|
+
let current = this.head[this.nextName];
|
|
172
|
+
return {
|
|
173
|
+
next: () => {
|
|
174
|
+
if (current === this.head) return {
|
|
175
|
+
done: true
|
|
176
|
+
};
|
|
177
|
+
const value = current;
|
|
178
|
+
current = current[this.nextName];
|
|
179
|
+
return {
|
|
180
|
+
value
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
getIterable(from, to) {
|
|
186
|
+
return {
|
|
187
|
+
[Symbol.iterator]: () => {
|
|
188
|
+
let current = from instanceof SListHead.SListPtr && from.node || from || this.head[this.nextName];
|
|
189
|
+
const stop = to ? (to instanceof SListHead.SListPtr && to.node || to)[this.nextName] : this.head;
|
|
190
|
+
return {
|
|
191
|
+
next: () => {
|
|
192
|
+
if (current === stop) return {
|
|
193
|
+
done: true
|
|
194
|
+
};
|
|
195
|
+
const value = current;
|
|
196
|
+
current = current[this.nextName];
|
|
197
|
+
return {
|
|
198
|
+
value
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
getPtrIterable(from, to) {
|
|
206
|
+
return {
|
|
207
|
+
[Symbol.iterator]: () => {
|
|
208
|
+
let current = from instanceof SListHead.SListPtr ? from.clone() : from ? new SListHead.SListPtr(this, SListHead.getPrev(this, this.head, from)) : this.getPtr();
|
|
209
|
+
const stop = to ? (to instanceof SListHead.SListPtr && to.node || to)[this.nextName] : this.head;
|
|
210
|
+
return {
|
|
211
|
+
next: () => {
|
|
212
|
+
if (current.node === stop) return {
|
|
213
|
+
done: true
|
|
214
|
+
};
|
|
215
|
+
const value = current.clone();
|
|
216
|
+
current.next();
|
|
217
|
+
return {
|
|
218
|
+
value
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// static utilities
|
|
227
|
+
|
|
228
|
+
static pop({
|
|
229
|
+
nextName
|
|
230
|
+
}, prev) {
|
|
231
|
+
const node = prev[nextName];
|
|
232
|
+
prev[nextName] = node[nextName];
|
|
233
|
+
node[nextName] = node;
|
|
234
|
+
return {
|
|
235
|
+
node,
|
|
236
|
+
list: prev
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
static extract({
|
|
240
|
+
nextName
|
|
241
|
+
}, prevFrom, nodeTo) {
|
|
242
|
+
const node = prevFrom[nextName];
|
|
243
|
+
if (prevFrom === nodeTo) return {
|
|
244
|
+
prev: prevFrom,
|
|
245
|
+
node
|
|
246
|
+
};
|
|
247
|
+
prevFrom[nextName] = nodeTo[nextName];
|
|
248
|
+
nodeTo[nextName] = node;
|
|
249
|
+
return {
|
|
250
|
+
prev: nodeTo,
|
|
251
|
+
node
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
static splice({
|
|
255
|
+
nextName
|
|
256
|
+
}, prev1, {
|
|
257
|
+
prev,
|
|
258
|
+
node
|
|
259
|
+
}) {
|
|
260
|
+
prev[nextName] = prev1[nextName];
|
|
261
|
+
prev1[nextName] = node;
|
|
262
|
+
return prev1;
|
|
263
|
+
}
|
|
264
|
+
static getPrevPrev({
|
|
265
|
+
nextName
|
|
266
|
+
}, list, node) {
|
|
267
|
+
let prev = list,
|
|
268
|
+
current = prev[nextName];
|
|
269
|
+
while (current[nextName] !== list) {
|
|
270
|
+
if (node && current[nextName] === node) return prev;
|
|
271
|
+
prev = current;
|
|
272
|
+
current = prev[nextName];
|
|
273
|
+
}
|
|
274
|
+
if (node) {
|
|
275
|
+
if (list[nextName] === node) return current;
|
|
276
|
+
throw new Error('node does not belong to the list');
|
|
277
|
+
}
|
|
278
|
+
return prev;
|
|
279
|
+
}
|
|
280
|
+
static getPrev(names, list, node) {
|
|
281
|
+
return SListHead.getPrevPrev(names, list, node)[names.nextName];
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// node helpers
|
|
285
|
+
|
|
286
|
+
makeNode() {
|
|
287
|
+
const node = {};
|
|
288
|
+
node[this.nextName] = node;
|
|
289
|
+
return node;
|
|
290
|
+
}
|
|
291
|
+
adopt(node) {
|
|
292
|
+
if (node[this.nextName]) {
|
|
293
|
+
if (node[this.nextName] === node) return node;
|
|
294
|
+
throw new Error('node is already a part of a list, or there is a name clash');
|
|
295
|
+
}
|
|
296
|
+
node[this.nextName] = node;
|
|
297
|
+
return node;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// helpers
|
|
301
|
+
|
|
302
|
+
clone() {
|
|
303
|
+
return new SListHead(this);
|
|
304
|
+
}
|
|
305
|
+
make(newHead = null) {
|
|
306
|
+
return new SListHead(newHead, this);
|
|
307
|
+
}
|
|
308
|
+
makeFrom(values) {
|
|
309
|
+
return SListHead.from(values, this);
|
|
310
|
+
}
|
|
311
|
+
pushValuesFront(values) {
|
|
312
|
+
for (const value of values) {
|
|
313
|
+
this.pushFront(value);
|
|
314
|
+
}
|
|
315
|
+
return this;
|
|
316
|
+
}
|
|
317
|
+
appendValuesFront(values) {
|
|
318
|
+
return this.appendFront(SListHead.from(values, this));
|
|
319
|
+
}
|
|
320
|
+
static from(values, options) {
|
|
321
|
+
const list = new SListHead(null, options),
|
|
322
|
+
nextName = list.nextName;
|
|
323
|
+
let prev = list.head;
|
|
324
|
+
for (const value of values) {
|
|
325
|
+
list.adopt(value);
|
|
326
|
+
prev[nextName] = value;
|
|
327
|
+
prev = value;
|
|
328
|
+
}
|
|
329
|
+
prev[nextName] = list.head;
|
|
330
|
+
return list;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
SListHead.defaults = {
|
|
334
|
+
nextName: 'next'
|
|
335
|
+
};
|
|
336
|
+
SListHead.prototype.pop = SListHead.prototype.popFront;
|
|
337
|
+
SListHead.prototype.push = SListHead.prototype.pushFront;
|
|
338
|
+
SListHead.prototype.append = SListHead.prototype.appendBack;
|
|
339
|
+
SListHead.Unsafe = class Unsafe {
|
|
340
|
+
constructor(head) {
|
|
341
|
+
this.head = head;
|
|
342
|
+
}
|
|
343
|
+
};
|
|
344
|
+
SListHead.SListPtr = class SListPtr {
|
|
345
|
+
constructor(list, prev) {
|
|
346
|
+
this.list = list;
|
|
347
|
+
this.prev = prev || list.head;
|
|
348
|
+
}
|
|
349
|
+
get node() {
|
|
350
|
+
return this.prev[this.list.nextName];
|
|
351
|
+
}
|
|
352
|
+
get isHead() {
|
|
353
|
+
return this.prev[this.list.nextName] === this.list.head;
|
|
354
|
+
}
|
|
355
|
+
next() {
|
|
356
|
+
this.prev = this.prev[this.list.nextName];
|
|
357
|
+
return this;
|
|
358
|
+
}
|
|
359
|
+
clone() {
|
|
360
|
+
return new SListHead.SListPtr(this.list, this.prev);
|
|
361
|
+
}
|
|
362
|
+
};
|
|
363
|
+
var _default = exports.default = SListHead;
|
package/cjs/package.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type":"commonjs"}
|
package/cjs/utils.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.lessFromCompare = exports.greaterFromLess = exports.equalFromLess = exports.copyOptions = exports.compareFromLess = exports.binarySearch = void 0;
|
|
7
|
+
const compareFromLess = lessFn => (a, b) => lessFn(a, b) ? -1 : lessFn(b, a) ? 1 : 0;
|
|
8
|
+
exports.compareFromLess = compareFromLess;
|
|
9
|
+
const lessFromCompare = compareFn => (a, b) => compareFn(a, b) < 0;
|
|
10
|
+
exports.lessFromCompare = lessFromCompare;
|
|
11
|
+
const equalFromLess = lessFn => (a, b) => !lessFn(a, b) && !lessFn(b, a);
|
|
12
|
+
exports.equalFromLess = equalFromLess;
|
|
13
|
+
const greaterFromLess = lessFn => (a, b) => lessFn(b, a);
|
|
14
|
+
exports.greaterFromLess = greaterFromLess;
|
|
15
|
+
const binarySearch = (sortedArray, lessValueFn, from = 0, to = sortedArray.length) => {
|
|
16
|
+
let left = from,
|
|
17
|
+
right = to;
|
|
18
|
+
while (left < right) {
|
|
19
|
+
const mid = left + right >> 1;
|
|
20
|
+
if (lessValueFn(sortedArray[mid])) {
|
|
21
|
+
left = mid + 1;
|
|
22
|
+
} else {
|
|
23
|
+
right = mid;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return right;
|
|
27
|
+
};
|
|
28
|
+
exports.binarySearch = binarySearch;
|
|
29
|
+
const copyOptions = (target, pattern, ...sources) => {
|
|
30
|
+
target = target || {};
|
|
31
|
+
const keys = Object.keys(pattern);
|
|
32
|
+
for (const key of keys) {
|
|
33
|
+
target[key] = pattern[key];
|
|
34
|
+
}
|
|
35
|
+
for (const source of sources) {
|
|
36
|
+
if (!source || typeof source !== 'object') continue;
|
|
37
|
+
for (const key of keys) {
|
|
38
|
+
if (key in source) target[key] = source[key];
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return target;
|
|
42
|
+
};
|
|
43
|
+
exports.copyOptions = copyOptions;
|
package/package.json
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "list-toolkit",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "List-based data structures to organize your objects.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"exports": {
|
|
7
|
+
"import": "./src/*",
|
|
8
|
+
"default": "./cjs/*"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"test": "tape6 --flags FO",
|
|
12
|
+
"prepareDist": "node scripts/prepareDist.js",
|
|
13
|
+
"build": "babel src --out-dir cjs",
|
|
14
|
+
"prepublishOnly": "npm run prepareDist && npm run build"
|
|
15
|
+
},
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "git+https://github.com/uhop/list-toolkit.git"
|
|
19
|
+
},
|
|
20
|
+
"keywords": [
|
|
21
|
+
"list",
|
|
22
|
+
"lists",
|
|
23
|
+
"cache",
|
|
24
|
+
"heap",
|
|
25
|
+
"data structures"
|
|
26
|
+
],
|
|
27
|
+
"author": "Eugene Lazutkin <eugene.lazutkin@gmail.com> (http://www.lazutkin.com/)",
|
|
28
|
+
"license": "BSD-3-Clause",
|
|
29
|
+
"bugs": {
|
|
30
|
+
"url": "https://github.com/uhop/list-toolkit/issues"
|
|
31
|
+
},
|
|
32
|
+
"homepage": "https://github.com/uhop/list-toolkit#readme",
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"@babel/cli": "^7.24.5",
|
|
35
|
+
"@babel/core": "^7.24.5",
|
|
36
|
+
"@babel/preset-env": "^7.24.5",
|
|
37
|
+
"tape-six": "^0.9.5"
|
|
38
|
+
},
|
|
39
|
+
"files": [
|
|
40
|
+
"/src",
|
|
41
|
+
"/cjs"
|
|
42
|
+
],
|
|
43
|
+
"babel": {
|
|
44
|
+
"presets": [
|
|
45
|
+
[
|
|
46
|
+
"@babel/preset-env",
|
|
47
|
+
{
|
|
48
|
+
"targets": {
|
|
49
|
+
"node": "current"
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
]
|
|
53
|
+
]
|
|
54
|
+
},
|
|
55
|
+
"tape6": {
|
|
56
|
+
"tests": [
|
|
57
|
+
"/tests/test-*.*js"
|
|
58
|
+
]
|
|
59
|
+
}
|
|
60
|
+
}
|
package/src/Cache.js
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
import List from './List.js';
|
|
4
|
+
|
|
5
|
+
class Cache {
|
|
6
|
+
constructor(capacity = 10) {
|
|
7
|
+
this.capacity = capacity;
|
|
8
|
+
this.size = 0;
|
|
9
|
+
this.list = new List();
|
|
10
|
+
this.dict = {};
|
|
11
|
+
}
|
|
12
|
+
find(key) {
|
|
13
|
+
const node = this.dict[key];
|
|
14
|
+
if (typeof node == 'object') {
|
|
15
|
+
return node.value.value;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
remove(key) {
|
|
19
|
+
const node = this.dict[key];
|
|
20
|
+
if (typeof node == 'object') {
|
|
21
|
+
delete this.dict[key];
|
|
22
|
+
node.pop();
|
|
23
|
+
--this.size;
|
|
24
|
+
}
|
|
25
|
+
return this;
|
|
26
|
+
}
|
|
27
|
+
register(key, value) {
|
|
28
|
+
const node = this.dict[key];
|
|
29
|
+
if (typeof node == 'object') {
|
|
30
|
+
this.list.moveToFront(node);
|
|
31
|
+
node.value.value = value;
|
|
32
|
+
return this;
|
|
33
|
+
}
|
|
34
|
+
if (this.size >= this.capacity) {
|
|
35
|
+
const node = this.list.back;
|
|
36
|
+
this.list.moveToFront(node);
|
|
37
|
+
delete this.dict[node.value.key];
|
|
38
|
+
this.dict[key] = node;
|
|
39
|
+
node.value = {key, value};
|
|
40
|
+
return this;
|
|
41
|
+
}
|
|
42
|
+
this.list.pushFront({key, value});
|
|
43
|
+
++this.size;
|
|
44
|
+
this.dict[key] = this.list.front;
|
|
45
|
+
return this;
|
|
46
|
+
}
|
|
47
|
+
clear() {
|
|
48
|
+
this.dict = {};
|
|
49
|
+
this.list.clear();
|
|
50
|
+
this.size = 0;
|
|
51
|
+
return this;
|
|
52
|
+
}
|
|
53
|
+
[Symbol.iterator]() {
|
|
54
|
+
return this.list[Symbol.iterator]();
|
|
55
|
+
}
|
|
56
|
+
getReverseIterable() {
|
|
57
|
+
return this.list.getReverseIterable();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export default Cache;
|