solists 0.2.0 → 1.0.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.
@@ -3,11 +3,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.DoublyLinkedList = void 0;
4
4
  const Node_1 = require("./Node");
5
5
  class DoublyLinkedList {
6
- constructor(rearrangeOnCreation = false, iterable = null) {
7
- this.head = null;
8
- this.tail = null;
9
- this.length = 0;
10
- this.rearrangeOnCreation = rearrangeOnCreation;
6
+ constructor(iterable = null, options = {}) {
7
+ var _a;
8
+ this._options = options;
9
+ this._head = null;
10
+ this._tail = null;
11
+ this._length = 0;
12
+ this._accessOnly = (_a = options.accessOnly) !== null && _a !== void 0 ? _a : true;
11
13
  if (iterable !== null) {
12
14
  this._extend(iterable);
13
15
  }
@@ -15,96 +17,94 @@ class DoublyLinkedList {
15
17
  [Symbol.iterator]() {
16
18
  return this._values();
17
19
  }
18
- // Public Array-like methods
20
+ // Public native Array methods
19
21
  at(index) {
20
22
  if (this.length === 0 || Math.abs(index) >= this.length) {
21
23
  return undefined;
22
24
  }
23
25
  index = this._toAbsoluteIndex(index, this.length);
24
26
  const targetNode = this._getNode(index);
25
- if (targetNode === null) {
26
- return undefined;
27
- }
28
27
  targetNode.count += 1;
29
28
  this._rearrange(targetNode);
30
29
  return targetNode.value;
31
30
  }
32
- concat(...values) {
33
- const { length: valuesLength } = values;
34
- const result = this.slice(0, this.length);
35
- for (let index = 0; index < valuesLength; index += 1) {
36
- const value = values[index];
37
- if (value instanceof DoublyLinkedList || Array.isArray(value)) {
38
- for (const currentValue of value.values()) {
39
- result.push(currentValue);
31
+ concat(...items) {
32
+ const result = this.slice();
33
+ for (const item of items) {
34
+ if (Array.isArray(item) || item instanceof DoublyLinkedList) {
35
+ for (const value of item) {
36
+ result.push(value);
40
37
  }
41
38
  }
42
39
  else {
43
- result.push(value);
40
+ result.push(item);
44
41
  }
45
42
  }
46
43
  return result;
47
44
  }
48
- copyWithin(target /* = 0 */, start /* = 0, end = @length */) {
45
+ copyWithin(target, start, end) {
46
+ const targetIndex = this._toAbsoluteIndex(target, this.length);
49
47
  const sourceStart = this._toAbsoluteIndex(start, this.length);
50
- const sourceEnd = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : this.length;
51
- const targetStart = this._toAbsoluteIndex(target, this.length);
52
- let count = Math.min((sourceEnd === this.length ? this.length : this._toAbsoluteIndex(sourceEnd, this.length)) - sourceStart, this.length - targetStart);
53
- const tempSrcLst = this.slice(0, this.length);
54
- const targetNodes = this._nodes(targetStart, targetStart + count);
55
- const sourceNodes = tempSrcLst._nodes(sourceStart, sourceStart + count);
56
- while (count > 0) {
57
- const targetCurrentNode = targetNodes.next();
58
- const sourceCurrentNode = sourceNodes.next();
59
- const targetCurrentValue = targetCurrentNode.value;
60
- const sourceCurrentValue = sourceCurrentNode.value;
61
- targetCurrentValue[1].value = sourceCurrentValue[1].value;
62
- count -= 1;
48
+ const sourceEnd = end === undefined ? this.length : this._toAbsoluteIndex(end, this.length);
49
+ let count = Math.min(sourceEnd - sourceStart, this.length - targetIndex);
50
+ if (count <= 0 || sourceStart === targetIndex)
51
+ return this;
52
+ if (sourceStart < targetIndex && targetIndex < sourceStart + count) {
53
+ let sourceNode = this._getNode(sourceStart + count - 1);
54
+ let targetNode = this._getNode(targetIndex + count - 1);
55
+ while (count > 0) {
56
+ targetNode.value = sourceNode.value;
57
+ sourceNode = sourceNode.prev;
58
+ targetNode = targetNode.prev;
59
+ count -= 1;
60
+ }
61
+ }
62
+ else {
63
+ let sourceNode = this._getNode(sourceStart);
64
+ let targetNode = this._getNode(targetIndex);
65
+ while (count > 0) {
66
+ targetNode.value = sourceNode.value;
67
+ sourceNode = sourceNode.next;
68
+ targetNode = targetNode.next;
69
+ count -= 1;
70
+ }
63
71
  }
64
72
  return this;
65
73
  }
66
74
  entries() {
67
75
  return this._entries();
68
76
  }
69
- // TODO: Support "thisArg" argument
70
- every(callbackFn) {
77
+ every(predicate, thisArg) {
78
+ this._aCallable(predicate);
71
79
  for (const [index, node] of this._nodes(0, this.length)) {
72
- if (!(callbackFn(node.value, index, this))) {
80
+ if (!predicate.call(thisArg, node.value, index, this)) {
73
81
  return false;
74
82
  }
75
83
  }
76
84
  return true;
77
85
  }
78
- fill(value) {
79
- let startIndex = undefined;
80
- if (arguments.length > 1) {
81
- startIndex = arguments[1];
82
- }
83
- startIndex = this._toAbsoluteIndex(startIndex, this.length);
84
- let endIndex = undefined;
85
- if (arguments.length > 2) {
86
- endIndex = arguments[2];
87
- }
88
- endIndex = (endIndex === undefined) ? this.length : this._toAbsoluteIndex(endIndex, this.length);
89
- for (const [/* index */ , node] of this._nodes(startIndex, endIndex)) {
86
+ fill(value, start, end) {
87
+ const startIndex = this._toAbsoluteIndex(start, this.length);
88
+ const endIndex = end === undefined ? this.length : this._toAbsoluteIndex(end, this.length);
89
+ for (const [, node] of this._nodes(startIndex, endIndex)) {
90
90
  node.value = value;
91
91
  }
92
92
  return this;
93
93
  }
94
- // TODO: Support "thisArg" argument
95
- filter(callbackFn) {
94
+ filter(predicate, thisArg) {
95
+ this._aCallable(predicate);
96
96
  const result = new DoublyLinkedList();
97
97
  for (const [index, node] of this._nodes(0, this.length)) {
98
- if (callbackFn(node.value, index, this)) {
98
+ if (predicate.call(thisArg, node.value, index, this)) {
99
99
  result.push(node.value);
100
100
  }
101
101
  }
102
102
  return result;
103
103
  }
104
- // TODO: Support "thisArg" argument
105
- find(callbackFn) {
104
+ find(predicate, thisArg) {
105
+ this._aCallable(predicate);
106
106
  for (const [index, node] of this._nodes(0, this.length)) {
107
- if (callbackFn(node.value, index, this)) {
107
+ if (predicate.call(thisArg, node.value, index, this)) {
108
108
  node.count += 1;
109
109
  this._rearrange(node);
110
110
  return node.value;
@@ -112,21 +112,21 @@ class DoublyLinkedList {
112
112
  }
113
113
  return undefined;
114
114
  }
115
- // TODO: Support "thisArg" argument
116
- findIndex(callbackFn) {
115
+ findIndex(predicate, thisArg) {
116
+ this._aCallable(predicate);
117
117
  for (const [index, node] of this._nodes(0, this.length)) {
118
- if (callbackFn(node.value, index, this)) {
118
+ if (predicate.call(thisArg, node.value, index, this)) {
119
119
  node.count += 1;
120
120
  const result = this._rearrange(node);
121
- return (result === undefined) ? index : result;
121
+ return result === undefined ? index : result;
122
122
  }
123
123
  }
124
124
  return -1;
125
125
  }
126
- // TODO: Support "thisArg" argument
127
- findLast(callbackFn) {
126
+ findLast(predicate, thisArg) {
127
+ this._aCallable(predicate);
128
128
  for (const [index, node] of this._nodesReverse(0, this.length)) {
129
- if (callbackFn(node.value, index, this)) {
129
+ if (predicate.call(thisArg, node.value, index, this)) {
130
130
  node.count += 1;
131
131
  this._rearrange(node);
132
132
  return node.value;
@@ -134,43 +134,56 @@ class DoublyLinkedList {
134
134
  }
135
135
  return undefined;
136
136
  }
137
- // TODO: Support "thisArg" argument
138
- findLastIndex(callbackFn) {
137
+ findLastIndex(predicate, thisArg) {
138
+ this._aCallable(predicate);
139
139
  for (const [index, node] of this._nodesReverse(0, this.length)) {
140
- if (callbackFn(node.value, index, this)) {
140
+ if (predicate.call(thisArg, node.value, index, this)) {
141
141
  node.count += 1;
142
142
  const result = this._rearrange(node);
143
- return (result === undefined) ? index : result;
143
+ return result === undefined ? index : result;
144
144
  }
145
145
  }
146
146
  return -1;
147
147
  }
148
- flat(depth = 1) {
149
- depth = this._toIntegerOrInfinity(depth);
150
- if (depth < 1) {
151
- return this.slice(0, this.length);
148
+ flat(depth) {
149
+ const d = depth === undefined ? 1 : this._toIntegerOrInfinity(depth);
150
+ if (d < 1) {
151
+ return this.slice();
152
152
  }
153
- return this.reduce(function (flat, toFlatten) {
154
- return flat.concat(((toFlatten instanceof DoublyLinkedList) && (depth > 1)) ? toFlatten.flat(depth - 1) : toFlatten);
155
- }, new DoublyLinkedList());
153
+ const result = new DoublyLinkedList();
154
+ for (const [, node] of this._nodes(0, this.length)) {
155
+ const value = node.value;
156
+ if (Array.isArray(value) || value instanceof DoublyLinkedList) {
157
+ const flattened = value instanceof DoublyLinkedList
158
+ ? value.flat(d - 1)
159
+ : new DoublyLinkedList(value).flat(d - 1);
160
+ for (const item of flattened) {
161
+ result.push(item);
162
+ }
163
+ }
164
+ else {
165
+ result.push(value);
166
+ }
167
+ }
168
+ return result;
156
169
  }
157
- // TODO: Support "thisArg" argument
158
- flatMap(callbackFn) {
159
- return this.map(callbackFn).flat();
170
+ flatMap(callback, thisArg) {
171
+ this._aCallable(callback);
172
+ return this.map(callback, thisArg).flat();
160
173
  }
161
- forEach(callbackFn) {
174
+ forEach(callbackfn, thisArg) {
175
+ this._aCallable(callbackfn);
162
176
  for (const [index, node] of this._nodes(0, this.length)) {
163
- callbackFn(node.value, index, this);
177
+ callbackfn.call(thisArg, node.value, index, this);
164
178
  }
165
- return undefined;
166
179
  }
167
- includes(searchedValue, fromIndex) {
180
+ includes(searchElement, fromIndex) {
168
181
  if (this.length === 0) {
169
182
  return false;
170
183
  }
171
- fromIndex = this._toAbsoluteIndex(fromIndex, this.length);
172
- for (const [/* index */ , node] of this._nodes(fromIndex, this.length)) {
173
- if (this._sameValueZero(node.value, searchedValue)) {
184
+ const startIndex = this._toAbsoluteIndex(fromIndex, this.length);
185
+ for (const [, node] of this._nodes(startIndex, this.length)) {
186
+ if (this._sameValueZero(node.value, searchElement)) {
174
187
  node.count += 1;
175
188
  this._rearrange(node);
176
189
  return true;
@@ -178,66 +191,62 @@ class DoublyLinkedList {
178
191
  }
179
192
  return false;
180
193
  }
181
- indexOf(searchedValue, fromIndex = 0) {
194
+ indexOf(searchElement, fromIndex) {
182
195
  if (this.length === 0) {
183
196
  return -1;
184
197
  }
185
- fromIndex = this._toAbsoluteIndex(fromIndex, this.length);
186
- for (const [index, node] of this._nodes(fromIndex, this.length)) {
187
- if (this._isStrictlyEqual(node.value, searchedValue)) {
198
+ const startIndex = this._toAbsoluteIndex(fromIndex !== null && fromIndex !== void 0 ? fromIndex : 0, this.length);
199
+ for (const [index, node] of this._nodes(startIndex, this.length)) {
200
+ if (this._isStrictlyEqual(node.value, searchElement)) {
188
201
  node.count += 1;
189
202
  const result = this._rearrange(node);
190
- return (result === undefined) ? index : result;
203
+ return result === undefined ? index : result;
191
204
  }
192
205
  }
193
206
  return -1;
194
207
  }
195
208
  join(separator) {
196
- let result = '';
197
209
  if (this.length === 0) {
198
- return result;
199
- }
200
- if (separator === undefined) {
201
- separator = ',';
210
+ return "";
202
211
  }
212
+ const sep = separator === undefined ? "," : String(separator);
213
+ let result = "";
203
214
  for (const [index, node] of this._nodes(0, this.length)) {
204
- const value = node.value == null ? "" : node.value;
205
- if (index !== this.length - 1) {
206
- result = result.concat(value) + separator;
207
- }
208
- else {
209
- result = result.concat(value);
210
- }
215
+ const value = node.value == null ? "" : String(node.value);
216
+ result += index === 0 ? value : sep + value;
211
217
  }
212
218
  return result;
213
219
  }
214
220
  keys() {
215
221
  return this._keys();
216
222
  }
217
- lastIndexOf(searchElement /* , fromIndex = @[*-1] */) {
223
+ get length() {
224
+ return this._length;
225
+ }
226
+ lastIndexOf(searchElement, fromIndex) {
218
227
  if (this.length === 0) {
219
228
  return -1;
220
229
  }
221
- let fromIndex = this.length - 1;
222
- if (arguments.length > 1) {
223
- fromIndex = Math.min(fromIndex, this._toIntegerOrInfinity(arguments[1]));
224
- }
225
- if (fromIndex < 0) {
226
- fromIndex = this.length + fromIndex;
230
+ let startIndex = arguments.length > 1
231
+ ? Math.min(this._toIntegerOrInfinity(fromIndex), this.length - 1)
232
+ : this.length - 1;
233
+ if (startIndex < 0) {
234
+ startIndex = this.length + startIndex;
227
235
  }
228
- for (const [index, node] of this._nodesReverse(0, fromIndex + 1)) {
236
+ for (const [index, node] of this._nodesReverse(0, startIndex + 1)) {
229
237
  if (this._isStrictlyEqual(node.value, searchElement)) {
230
238
  node.count += 1;
231
239
  const result = this._rearrange(node);
232
- return (result === undefined) ? index : result;
240
+ return result === undefined ? index : result;
233
241
  }
234
242
  }
235
243
  return -1;
236
244
  }
237
- map(callbackFn) {
245
+ map(callbackfn, thisArg) {
246
+ this._aCallable(callbackfn);
238
247
  const result = new DoublyLinkedList();
239
248
  for (const [index, node] of this._nodes(0, this.length)) {
240
- result.push(callbackFn(node.value, index, this));
249
+ result.push(callbackfn.call(thisArg, node.value, index, this));
241
250
  }
242
251
  return result;
243
252
  }
@@ -245,78 +254,72 @@ class DoublyLinkedList {
245
254
  if (this.length === 0) {
246
255
  return undefined;
247
256
  }
248
- const value = this.tail.value;
257
+ const value = this._tail.value;
249
258
  if (this.length === 1) {
250
259
  this._removeLast();
251
260
  }
252
261
  else {
253
- this.tail = this.tail.prev;
254
- this.tail.next = null;
255
- this.length -= 1;
262
+ this._tail = this._tail.prev;
263
+ this._tail.next = null;
264
+ this._length -= 1;
256
265
  }
257
266
  return value;
258
267
  }
259
- push(...values) {
260
- const { length: valuesLength } = values;
261
- for (let index = 0; index < valuesLength; index += 1) {
262
- const newNode = new Node_1.Node(values[index]);
268
+ push(...items) {
269
+ for (const item of items) {
270
+ const newNode = new Node_1.Node(item);
263
271
  if (this.length === 0) {
264
272
  this._insertFirst(newNode);
265
273
  }
266
- else if (this.tail !== null) {
267
- this._insertAfter(this.tail, newNode);
268
- }
269
274
  else {
270
- continue;
275
+ this._insertAfter(this._tail, newNode);
271
276
  }
272
- if (this.rearrangeOnCreation) {
277
+ if (!this._accessOnly) {
273
278
  this._rearrange(newNode);
274
279
  }
275
280
  }
276
281
  return this.length;
277
282
  }
278
- reduce(callbackFn, initialValue) {
279
- if (!(this._isCallable(callbackFn))) {
280
- throw TypeError(this._tryToString(callbackFn) + ' is not a function');
283
+ reduce(callbackfn, initialValue) {
284
+ this._aCallable(callbackfn);
285
+ const hasInitial = arguments.length > 1;
286
+ if (this.length === 0 && !hasInitial) {
287
+ throw TypeError("Reduce of empty list with no initial value");
281
288
  }
282
- if (this.length === 0 && arguments.length < 2) {
283
- throw TypeError('Reduce of empty list with no initial value');
284
- }
285
- let accumulator = arguments.length > 1 ? initialValue : this.head.value;
289
+ let accumulator = hasInitial ? initialValue : this._head.value;
286
290
  for (const [index, node] of this._nodes(0, this.length)) {
287
- if (arguments.length > 1 || index > 0) {
288
- accumulator = callbackFn(accumulator, node.value, index, this);
291
+ if (hasInitial || index > 0) {
292
+ accumulator = callbackfn(accumulator, node.value, index, this);
289
293
  }
290
294
  }
291
295
  return accumulator;
292
296
  }
293
- reduceRight(callbackFn, initialValue) {
294
- if (!(this._isCallable(callbackFn))) {
295
- throw TypeError(this._tryToString(callbackFn) + ' is not a function');
296
- }
297
- if (this.length === 0 && arguments.length < 2) {
298
- throw TypeError('Reduce of empty list with no initial value');
297
+ reduceRight(callbackfn, initialValue) {
298
+ this._aCallable(callbackfn);
299
+ const hasInitial = arguments.length > 1;
300
+ if (this.length === 0 && !hasInitial) {
301
+ throw TypeError("Reduce of empty list with no initial value");
299
302
  }
300
- let accumulator = arguments.length > 1 ? initialValue : this.tail.value;
303
+ let accumulator = hasInitial ? initialValue : this._tail.value;
301
304
  for (const [index, node] of this._nodesReverse(0, this.length)) {
302
- if (index < this.length - 1) {
303
- accumulator = callbackFn(accumulator, node.value, index, this);
305
+ if (hasInitial || index < this.length - 1) {
306
+ accumulator = callbackfn(accumulator, node.value, index, this);
304
307
  }
305
308
  }
306
309
  return accumulator;
307
310
  }
308
311
  reverse() {
309
312
  if (this.length > 1) {
310
- let curr = this.head;
313
+ let curr = this._head;
311
314
  while (curr) {
312
315
  const next = curr.next;
313
316
  curr.next = curr.prev;
314
317
  curr.prev = next;
315
318
  if (curr.next === null) {
316
- this.tail = curr;
319
+ this._tail = curr;
317
320
  }
318
321
  else if (curr.prev === null) {
319
- this.head = curr;
322
+ this._head = curr;
320
323
  }
321
324
  curr = next;
322
325
  }
@@ -327,68 +330,66 @@ class DoublyLinkedList {
327
330
  if (this.length === 0) {
328
331
  return undefined;
329
332
  }
330
- const value = this.head.value;
333
+ const value = this._head.value;
331
334
  if (this.length === 1) {
332
335
  this._removeLast();
333
336
  }
334
337
  else {
335
- this.head = this.head.next;
336
- this.head.prev = null;
337
- this.length -= 1;
338
+ this._head = this._head.next;
339
+ this._head.prev = null;
340
+ this._length -= 1;
338
341
  }
339
342
  return value;
340
343
  }
341
- slice(startIndex, endIndex) {
344
+ slice(start, end) {
342
345
  const result = new DoublyLinkedList();
343
- if (startIndex === undefined) {
344
- startIndex = 0;
345
- }
346
- startIndex = this._toAbsoluteIndex(startIndex, this.length);
347
- endIndex = this._toAbsoluteIndex(endIndex === undefined ? this.length : endIndex, this.length);
348
- for (const [/* index */ , node] of this._nodes(startIndex, endIndex)) {
346
+ const startIndex = this._toAbsoluteIndex(start, this.length);
347
+ const endIndex = end === undefined ? this.length : this._toAbsoluteIndex(end, this.length);
348
+ for (const [, node] of this._nodes(startIndex, endIndex)) {
349
349
  result.push(node.value);
350
350
  }
351
351
  return result;
352
352
  }
353
- // TODO: Support "thisArg" argument
354
- some(callbackFn) {
353
+ some(predicate, thisArg) {
354
+ this._aCallable(predicate);
355
355
  for (const [index, node] of this._nodes(0, this.length)) {
356
- if (callbackFn(node.value, index, this)) {
356
+ if (predicate.call(thisArg, node.value, index, this)) {
357
357
  return true;
358
358
  }
359
359
  }
360
360
  return false;
361
361
  }
362
- sort(comparefn) {
362
+ sort(compareFn) {
363
363
  if (this.length > 1) {
364
- this._mergeSort(this._getSortCompare(comparefn));
364
+ const compare = this._getSortCompare(compareFn);
365
+ if (this.length < 8) {
366
+ this._insertionSort(compare);
367
+ }
368
+ else {
369
+ this._mergeSort(compare);
370
+ }
365
371
  }
366
372
  return this;
367
373
  }
368
- splice(start, deleteCount /* , ...items */) {
374
+ splice(start, deleteCount, ...items) {
369
375
  if (arguments.length === 0) {
370
- deleteCount = 0;
371
- }
372
- else if (arguments.length === 1) {
373
- start = this._toAbsoluteIndex(start, this.length);
374
- deleteCount = this.length - start;
375
- }
376
- else {
377
- start = this._toAbsoluteIndex(start, this.length);
378
- deleteCount = Math.min(Math.max(this._toIntegerOrInfinity(deleteCount), 0), this.length - start);
376
+ return new DoublyLinkedList();
379
377
  }
378
+ const startIndex = this._toAbsoluteIndex(start, this.length);
379
+ const delCount = arguments.length === 1
380
+ ? this.length - startIndex
381
+ : Math.min(Math.max(this._toIntegerOrInfinity(deleteCount), 0), this.length - startIndex);
380
382
  const deleted = new DoublyLinkedList();
381
- if (this.length > 0 && deleteCount > 0) {
382
- let prev = this._getNode(start - 1);
383
- let current = prev ? prev.next : this.head;
384
- for (let index = 0; index < deleteCount; index += 1) {
383
+ if (this.length > 0 && delCount > 0) {
384
+ const prev = this._getNode(startIndex - 1);
385
+ let current = prev ? prev.next : this._head;
386
+ for (let i = 0; i < delCount; i++) {
385
387
  deleted.push(current.value);
386
388
  current = current.next;
387
- this.length -= 1;
389
+ this._length -= 1;
388
390
  }
389
391
  if (prev === null) {
390
- this.head = current;
391
- prev = current;
392
+ this._head = current;
392
393
  if (current) {
393
394
  current.prev = null;
394
395
  }
@@ -399,83 +400,99 @@ class DoublyLinkedList {
399
400
  current.prev = prev;
400
401
  }
401
402
  else {
402
- this.tail = prev;
403
+ this._tail = prev;
403
404
  }
404
405
  }
405
406
  }
406
- const items = Array.prototype.slice.call(arguments, 2, arguments.length);
407
407
  if (items.length > 0) {
408
- let current, next;
409
- if (start === 0) {
410
- next = this.head;
411
- this.head = new Node_1.Node(items.shift());
412
- current = this.head;
413
- this.length += 1;
408
+ let current;
409
+ let next;
410
+ if (startIndex === 0) {
411
+ next = this._head;
412
+ this._head = new Node_1.Node(items.shift());
413
+ current = this._head;
414
+ this._length += 1;
414
415
  }
415
416
  else {
416
- current = this._getNode(start - 1);
417
+ current = this._getNode(startIndex - 1);
417
418
  next = current.next;
418
419
  }
419
420
  for (const item of items) {
420
421
  current.next = new Node_1.Node(item);
421
422
  current.next.prev = current;
422
423
  current = current.next;
423
- this.length += 1;
424
+ this._length += 1;
424
425
  }
425
426
  current.next = next;
426
427
  if (next) {
427
428
  next.prev = current;
428
429
  }
429
430
  else {
430
- this.tail = current;
431
+ this._tail = current;
431
432
  }
432
433
  }
433
434
  return deleted;
434
435
  }
435
436
  toLocaleString(locales, options) {
436
- let result = '';
437
437
  if (this.length === 0) {
438
- return result;
438
+ return "";
439
439
  }
440
- const separator = ',';
441
- for (const [index, node] of this._nodes(0, this.length)) {
442
- const value = node.value == null ? "" : node.value;
443
- if (index !== this.length - 1) {
444
- if (locales == null || options == null) {
445
- result = result.concat(value.toLocaleString()) + separator;
446
- }
447
- else {
448
- result = result.concat(value.toLocaleString(locales, options)) + separator;
449
- }
440
+ const parts = [];
441
+ for (const [, node] of this._nodes(0, this.length)) {
442
+ const value = node.value;
443
+ if (value == null) {
444
+ parts.push("");
450
445
  }
451
446
  else {
452
- if (locales == null || options == null) {
453
- result = result.concat(value.toLocaleString());
454
- }
455
- else {
456
- result = result.concat(value.toLocaleString(locales, options));
457
- }
447
+ parts.push(value.toLocaleString(locales, options));
458
448
  }
459
449
  }
460
- return result;
450
+ return parts.join(",");
451
+ }
452
+ toReversed() {
453
+ return this.slice().reverse();
454
+ }
455
+ toSorted(compareFn) {
456
+ if (compareFn !== undefined && !this._isCallable(compareFn)) {
457
+ let value;
458
+ if (compareFn === null)
459
+ value = "null";
460
+ else if (Array.isArray(compareFn))
461
+ value = Object.prototype.toString.call(compareFn);
462
+ else if (typeof compareFn === "object")
463
+ value = "#<Object>";
464
+ else
465
+ value = String(compareFn);
466
+ throw TypeError(`The comparison function must be either a function or undefined: ${value}`);
467
+ }
468
+ return this.slice().sort(compareFn);
469
+ }
470
+ toSpliced(start, deleteCount, ...items) {
471
+ const copy = this.slice();
472
+ if (arguments.length === 0) {
473
+ return copy;
474
+ }
475
+ else if (arguments.length === 1) {
476
+ copy.splice(start);
477
+ }
478
+ else {
479
+ copy.splice(start, deleteCount, ...items);
480
+ }
481
+ return copy;
461
482
  }
462
483
  toString() {
463
484
  return this.join(",");
464
485
  }
465
- unshift(...values) {
466
- const { length: valuesLength } = values;
467
- for (let index = valuesLength - 1; index >= 0; index -= 1) {
468
- const newNode = new Node_1.Node(values[index]);
486
+ unshift(...items) {
487
+ for (let i = items.length - 1; i >= 0; i--) {
488
+ const newNode = new Node_1.Node(items[i]);
469
489
  if (this.length === 0) {
470
490
  this._insertFirst(newNode);
471
491
  }
472
- else if (this.head !== null) {
473
- this._insertBefore(this.head, newNode);
474
- }
475
492
  else {
476
- continue;
493
+ this._insertBefore(this._head, newNode);
477
494
  }
478
- if (this.rearrangeOnCreation) {
495
+ if (!this._accessOnly) {
479
496
  this._rearrange(newNode);
480
497
  }
481
498
  }
@@ -484,25 +501,35 @@ class DoublyLinkedList {
484
501
  values() {
485
502
  return this._values();
486
503
  }
504
+ with(index, value) {
505
+ const relativeIndex = this._toIntegerOrInfinity(index);
506
+ const actualIndex = relativeIndex < 0 ? this.length + relativeIndex : relativeIndex;
507
+ if (actualIndex >= this.length || actualIndex < 0) {
508
+ throw new RangeError("Invalid index : " + index);
509
+ }
510
+ const copy = this.slice();
511
+ const node = copy._getNode(actualIndex);
512
+ if (node !== null) {
513
+ node.value = value;
514
+ }
515
+ return copy;
516
+ }
487
517
  // Public custom methods
488
518
  insert(index, value) {
489
519
  if (index === undefined || arguments.length < 2) {
490
520
  return undefined;
491
521
  }
492
- index = this._toAbsoluteIndex(index, this.length);
493
- if (index === 0) {
522
+ const idx = this._toAbsoluteIndex(index, this.length);
523
+ if (idx === 0) {
494
524
  return this.unshift(value);
495
525
  }
496
- if (index === this.length) {
526
+ if (idx === this.length) {
497
527
  return this.push(value);
498
528
  }
499
- const prev = this._getNode(index - 1);
500
- if (prev === null) {
501
- return undefined;
502
- }
529
+ const prev = this._getNode(idx - 1);
503
530
  const newNode = new Node_1.Node(value);
504
531
  this._insertAfter(prev, newNode);
505
- if (this.rearrangeOnCreation) {
532
+ if (!this._accessOnly) {
506
533
  this._rearrange(newNode);
507
534
  }
508
535
  return this.length;
@@ -510,17 +537,17 @@ class DoublyLinkedList {
510
537
  isEmpty() {
511
538
  return this.length === 0;
512
539
  }
513
- isEqual(value) {
514
- if (!(this._isIterable(value))) {
540
+ isEqual(other) {
541
+ if (!this._isIterable(other)) {
515
542
  throw TypeError("The value should be iterable");
516
543
  }
517
- if (this.length !== value.length) {
544
+ if (this.length !== other.length) {
518
545
  return false;
519
546
  }
520
- const values = value.values();
521
- for (const [/* index */ , node] of this._nodes(0, this.length)) {
522
- const currentValue = values.next();
523
- if (!(this._sameValue(node.value, currentValue.value))) {
547
+ const otherIterator = other[Symbol.iterator]();
548
+ for (const [, node] of this._nodes(0, this.length)) {
549
+ const otherValue = otherIterator.next();
550
+ if (!this._sameValue(node.value, otherValue.value)) {
524
551
  return false;
525
552
  }
526
553
  }
@@ -530,23 +557,21 @@ class DoublyLinkedList {
530
557
  if (this.length === 0 || index === undefined) {
531
558
  return undefined;
532
559
  }
533
- index = this._toAbsoluteIndex(index, this.length);
534
- if (index >= this.length) {
535
- return undefined;
536
- }
537
- const node = this._getNode(index);
538
- if (node === null) {
560
+ const idx = this._toAbsoluteIndex(index, this.length);
561
+ if (idx >= this.length) {
539
562
  return undefined;
540
563
  }
564
+ const node = this._getNode(idx);
541
565
  const value = node.value;
542
566
  this._remove(node);
543
567
  return value;
544
568
  }
545
- // Protected helping methods
569
+ // Protected methods
546
570
  _getIndexByNode(node) {
547
571
  let count = 0;
548
- while (node.prev) {
549
- node = node.prev;
572
+ let current = node;
573
+ while (current.prev) {
574
+ current = current.prev;
550
575
  count += 1;
551
576
  }
552
577
  return count;
@@ -555,27 +580,27 @@ class DoublyLinkedList {
555
580
  if (index < 0 || index >= this.length) {
556
581
  return null;
557
582
  }
558
- let node = this.head;
583
+ let node = this._head;
559
584
  let counter = 0;
560
585
  while (node) {
561
586
  if (counter === index) {
562
587
  break;
563
588
  }
564
589
  node = node.next;
565
- counter = counter + 1;
590
+ counter += 1;
566
591
  }
567
592
  return node;
568
593
  }
569
594
  _insertFirst(newNode) {
570
- this.head = newNode;
571
- this.tail = newNode;
572
- this.length += 1;
595
+ this._head = newNode;
596
+ this._tail = newNode;
597
+ this._length += 1;
573
598
  }
574
599
  _insertBefore(existingNode, newNode) {
575
- if (existingNode.isEqual(this.head)) {
600
+ if (existingNode.isEqual(this._head)) {
576
601
  newNode.next = existingNode;
577
602
  newNode.prev = null;
578
- this.head = newNode;
603
+ this._head = newNode;
579
604
  }
580
605
  else if (existingNode.prev !== null) {
581
606
  newNode.next = existingNode;
@@ -583,46 +608,46 @@ class DoublyLinkedList {
583
608
  existingNode.prev.next = newNode;
584
609
  }
585
610
  existingNode.prev = newNode;
586
- this.length += 1;
611
+ this._length += 1;
587
612
  }
588
613
  _insertAfter(existingNode, newNode) {
589
614
  newNode.prev = existingNode;
590
- if (existingNode.isEqual(this.tail)) {
615
+ if (existingNode.isEqual(this._tail)) {
591
616
  newNode.next = null;
592
- this.tail = newNode;
617
+ this._tail = newNode;
593
618
  }
594
619
  else if (existingNode.next !== null) {
595
620
  newNode.next = existingNode.next;
596
621
  existingNode.next.prev = newNode;
597
622
  }
598
623
  existingNode.next = newNode;
599
- this.length += 1;
624
+ this._length += 1;
600
625
  }
601
626
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
602
- _rearrange(node) {
627
+ _rearrange(_node) {
603
628
  return undefined;
604
629
  }
605
630
  _remove(node) {
606
- if (node.isEqual(this.head)) {
631
+ if (node.isEqual(this._head)) {
607
632
  this.shift();
608
633
  }
609
- else if (node.isEqual(this.tail)) {
634
+ else if (node.isEqual(this._tail)) {
610
635
  this.pop();
611
636
  }
612
637
  else if (node.next !== null && node.prev !== null) {
613
638
  node.next.prev = node.prev;
614
639
  node.prev.next = node.next;
615
- this.length -= 1;
640
+ this._length -= 1;
616
641
  }
617
642
  }
618
643
  _removeLast() {
619
- this.head = null;
620
- this.tail = null;
621
- this.length = 0;
644
+ this._head = null;
645
+ this._tail = null;
646
+ this._length = 0;
622
647
  }
623
- // Private helping methods
648
+ // Private methods
624
649
  *_entries() {
625
- let node = this.head;
650
+ let node = this._head;
626
651
  let counter = 0;
627
652
  while (node) {
628
653
  yield [counter, node.value];
@@ -631,38 +656,54 @@ class DoublyLinkedList {
631
656
  }
632
657
  }
633
658
  _extend(iterable) {
634
- if (!(this._isIterable(iterable))) {
659
+ if (!this._isIterable(iterable)) {
635
660
  throw TypeError("The value should be iterable");
636
661
  }
637
- for (const currentValue of iterable) {
638
- this.push(currentValue);
662
+ for (const value of iterable) {
663
+ const newNode = new Node_1.Node(value);
664
+ if (this.length === 0) {
665
+ this._insertFirst(newNode);
666
+ }
667
+ else {
668
+ this._insertAfter(this._tail, newNode);
669
+ }
639
670
  }
640
671
  }
641
- _getSortCompare(comparefn) {
642
- return function (x, y) {
672
+ _getSortCompare(compareFn) {
673
+ return (x, y) => {
643
674
  if (y === undefined)
644
675
  return -1;
645
676
  if (x === undefined)
646
677
  return 1;
647
- if (comparefn !== undefined)
648
- return +comparefn(x, y) || 0;
649
- return String(x) > String(y) ? 1 : -1;
678
+ if (compareFn !== undefined)
679
+ return +compareFn(x, y) || 0;
680
+ const xStr = String(x);
681
+ const yStr = String(y);
682
+ return xStr > yStr ? 1 : xStr < yStr ? -1 : 0;
650
683
  };
651
684
  }
652
685
  _isCallable(fn) {
653
- return (typeof fn === 'function');
686
+ return typeof fn === "function";
687
+ }
688
+ _aCallable(argument) {
689
+ if (this._isCallable(argument))
690
+ return argument;
691
+ const type = typeof argument;
692
+ const value = this._tryToString(argument);
693
+ const typePrefix = type !== "undefined" ? type + " " : "";
694
+ throw TypeError(`${typePrefix}${value} is not a function`);
654
695
  }
655
696
  _isIterable(obj) {
656
697
  if (obj == null) {
657
698
  return false;
658
699
  }
659
- return typeof obj[Symbol.iterator] === 'function';
700
+ return typeof obj[Symbol.iterator] === "function";
660
701
  }
661
702
  _isStrictlyEqual(x, y) {
662
703
  return x === y;
663
704
  }
664
705
  *_keys() {
665
- let node = this.head;
706
+ let node = this._head;
666
707
  let counter = 0;
667
708
  while (node) {
668
709
  yield counter;
@@ -670,15 +711,10 @@ class DoublyLinkedList {
670
711
  counter += 1;
671
712
  }
672
713
  }
673
- _merge(head1, head2, comparefn) {
674
- if (head1 == null) {
675
- return head2;
676
- }
677
- else if (head2 == null) {
678
- return head1;
679
- }
680
- let node, head;
681
- if (comparefn(head1.value, head2.value) <= 0) {
714
+ _merge(head1, head2, compareFn) {
715
+ let node;
716
+ let head;
717
+ if (compareFn(head1.value, head2.value) <= 0) {
682
718
  head = node = head1;
683
719
  head1 = head1.next;
684
720
  }
@@ -687,7 +723,7 @@ class DoublyLinkedList {
687
723
  head2 = head2.next;
688
724
  }
689
725
  while (head1 !== null && head2 !== null) {
690
- if (comparefn(head1.value, head2.value) <= 0) {
726
+ if (compareFn(head1.value, head2.value) <= 0) {
691
727
  node.next = head1;
692
728
  head1.prev = node;
693
729
  node = head1;
@@ -710,13 +746,12 @@ class DoublyLinkedList {
710
746
  }
711
747
  return head;
712
748
  }
713
- _mergeSort(comparefn) {
714
- const lists = [];
715
- let start = this.head;
716
- let end;
749
+ _mergeSort(compareFn) {
750
+ let lists = [];
751
+ let start = this._head;
717
752
  while (start !== null) {
718
- end = start;
719
- while (end.next !== null && comparefn(end.value, end.next.value) <= 0) {
753
+ let end = start;
754
+ while (end.next !== null && compareFn(end.value, end.next.value) <= 0) {
720
755
  end = end.next;
721
756
  }
722
757
  const next = end.next;
@@ -726,38 +761,79 @@ class DoublyLinkedList {
726
761
  start = next;
727
762
  }
728
763
  while (lists.length > 1) {
729
- const first = lists.shift();
730
- const second = lists.shift();
731
- if (first !== undefined && second !== undefined) {
732
- lists.push(this._merge(first, second, comparefn));
764
+ const merged = [];
765
+ for (let i = 0; i < lists.length; i += 2) {
766
+ if (i + 1 < lists.length) {
767
+ merged.push(this._merge(lists[i], lists[i + 1], compareFn));
768
+ }
769
+ else {
770
+ merged.push(lists[i]);
771
+ }
733
772
  }
773
+ lists = merged;
734
774
  }
735
- this.tail = lists[0];
736
- this.head = lists[0];
737
- while (this.tail && this.tail.next) {
738
- this.tail = this.tail.next;
775
+ this._tail = lists[0];
776
+ this._head = lists[0];
777
+ while (this._tail && this._tail.next) {
778
+ this._tail = this._tail.next;
779
+ }
780
+ }
781
+ _insertionSort(compareFn) {
782
+ let current = this._head.next;
783
+ while (current !== null) {
784
+ const next = current.next;
785
+ let position = current.prev;
786
+ while (position !== null && compareFn(position.value, current.value) > 0) {
787
+ position = position.prev;
788
+ }
789
+ if (position !== current.prev) {
790
+ if (current.prev) {
791
+ current.prev.next = current.next;
792
+ }
793
+ if (current.next) {
794
+ current.next.prev = current.prev;
795
+ }
796
+ else {
797
+ this._tail = current.prev;
798
+ }
799
+ if (position === null) {
800
+ current.prev = null;
801
+ current.next = this._head;
802
+ this._head.prev = current;
803
+ this._head = current;
804
+ }
805
+ else {
806
+ current.prev = position;
807
+ current.next = position.next;
808
+ if (position.next) {
809
+ position.next.prev = current;
810
+ }
811
+ position.next = current;
812
+ }
813
+ }
814
+ current = next;
739
815
  }
740
816
  }
741
817
  *_nodes(startIndex, endIndex) {
742
- let node = this.head;
818
+ let node = this._head;
743
819
  let counter = 0;
744
820
  while (node) {
745
821
  if (startIndex <= counter && counter < endIndex) {
746
822
  yield [counter, node];
747
823
  }
748
824
  node = node.next;
749
- counter = counter + 1;
825
+ counter += 1;
750
826
  }
751
827
  }
752
828
  *_nodesReverse(startIndex, endIndex) {
753
- let node = this.tail;
829
+ let node = this._tail;
754
830
  let counter = this.length - 1;
755
831
  while (node) {
756
832
  if (startIndex <= counter && counter < endIndex) {
757
833
  yield [counter, node];
758
834
  }
759
835
  node = node.prev;
760
- counter = counter - 1;
836
+ counter -= 1;
761
837
  }
762
838
  }
763
839
  _sameValue(x, y) {
@@ -771,6 +847,8 @@ class DoublyLinkedList {
771
847
  return integer < 0 ? Math.max(integer + length, 0) : Math.min(integer, length);
772
848
  }
773
849
  _toIntegerOrInfinity(argument) {
850
+ if (argument === undefined)
851
+ return 0;
774
852
  const number = +argument;
775
853
  return number !== number || number === 0 ? 0 : Math.trunc(number);
776
854
  }
@@ -778,12 +856,12 @@ class DoublyLinkedList {
778
856
  try {
779
857
  return String(argument);
780
858
  }
781
- catch (error) {
782
- return 'Object';
859
+ catch (_a) {
860
+ return "Object";
783
861
  }
784
862
  }
785
863
  *_values() {
786
- let node = this.head;
864
+ let node = this._head;
787
865
  while (node) {
788
866
  yield node.value;
789
867
  node = node.next;