atomic-fns 1.1.7 → 1.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/README.md +51 -12
- package/dist/collections/BTree.d.ts +11 -10
- package/dist/collections/BTree.js +58 -80
- package/dist/collections/Heap.js +1 -1
- package/dist/collections/LRUCache.d.ts +6 -3
- package/dist/collections/LRUCache.js +24 -11
- package/dist/collections/SortedMap.js +2 -2
- package/dist/collections/SortedTree.d.ts +2 -2
- package/dist/collections/SortedTree.js +3 -2
- package/dist/collections/SplayTree.d.ts +7 -5
- package/dist/collections/SplayTree.js +39 -26
- package/dist/collections/Trie.d.ts +1 -1
- package/dist/collections/Trie.js +26 -26
- package/dist/collections/deque.d.ts +1 -1
- package/dist/collections/deque.js +17 -10
- package/dist/collections/frozenset.js +4 -1
- package/dist/collections/index.d.ts +13 -32
- package/dist/collections/index.js +210 -82
- package/dist/decimal/index.d.ts +5 -2
- package/dist/decimal/index.js +63 -27
- package/dist/functools/index.d.ts +6 -30
- package/dist/functools/index.js +24 -56
- package/dist/globals/index.d.ts +3 -20
- package/dist/globals/index.js +23 -39
- package/dist/i18n/currency.d.ts +3 -0
- package/dist/i18n/currency.js +22 -7
- package/dist/i18n/date/index.d.ts +17 -10
- package/dist/i18n/date/index.js +79 -58
- package/dist/i18n/date/utils.d.ts +4 -5
- package/dist/i18n/date/utils.js +15 -113
- package/dist/i18n/duration.d.ts +11 -10
- package/dist/i18n/duration.js +38 -32
- package/dist/i18n/format.d.ts +5 -2
- package/dist/i18n/format.js +81 -209
- package/dist/i18n/index.d.ts +2 -1
- package/dist/itertools/index.d.ts +9 -13
- package/dist/itertools/index.js +38 -41
- package/dist/math/index.d.ts +10 -27
- package/dist/math/index.js +16 -33
- package/dist/operators/index.d.ts +1 -5
- package/dist/operators/index.js +60 -40
- package/dist/random/index.js +9 -6
- package/dist/string/index.d.ts +1 -1
- package/dist/string/index.js +2 -4
- package/dist/types.d.ts +3 -3
- package/package.json +16 -21
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
*
|
|
4
4
|
* @module collections
|
|
5
5
|
*/
|
|
6
|
-
import { call, get,
|
|
6
|
+
import { call, get, isArrayLike, isDate, isEmpty, isFunction, isIterable, isNull, isObject, isRegExp } from '../globals/index.js';
|
|
7
7
|
import { enumerate } from '../itertools/index.js';
|
|
8
|
-
import { compare, eq,
|
|
8
|
+
import { compare, eq, identity } from '../operators/index.js';
|
|
9
9
|
export * from './abc.js';
|
|
10
10
|
export * from './BTree.js';
|
|
11
11
|
export * from './deque.js';
|
|
@@ -17,15 +17,30 @@ export * from './SortedSet.js';
|
|
|
17
17
|
export * from './SortedTree.js';
|
|
18
18
|
export * from './SplayTree.js';
|
|
19
19
|
export * from './Trie.js';
|
|
20
|
+
/** Assigns `key`, defining it where a plain write would set the prototype instead. */
|
|
21
|
+
function setOwn(obj, key, value) {
|
|
22
|
+
if (typeof key === 'string' && key !== '__proto__') {
|
|
23
|
+
obj[key] = value;
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
Object.defineProperty(obj, key, { value, enumerable: true, writable: true, configurable: true });
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/** `isEmpty` counts declared parameters and keys, which says nothing about these values. */
|
|
30
|
+
function isBlank(x) {
|
|
31
|
+
if (isPlainObject(x))
|
|
32
|
+
return Object.keys(x).length === 0;
|
|
33
|
+
return isEmpty(x) && typeof x !== 'function' && !isDate(x) && !isRegExp(x);
|
|
34
|
+
}
|
|
20
35
|
export function compact(arr) {
|
|
21
36
|
if (!arr)
|
|
22
37
|
return;
|
|
23
38
|
if (Array.isArray(arr))
|
|
24
|
-
return arr.filter((x) => !
|
|
39
|
+
return arr.filter((x) => !isBlank(x));
|
|
25
40
|
const result = {};
|
|
26
41
|
for (const key of Object.keys(arr)) {
|
|
27
|
-
if (!
|
|
28
|
-
result
|
|
42
|
+
if (!isBlank(arr[key])) {
|
|
43
|
+
setOwn(result, key, arr[key]);
|
|
29
44
|
}
|
|
30
45
|
}
|
|
31
46
|
return result;
|
|
@@ -34,7 +49,7 @@ export function count(obj, func) {
|
|
|
34
49
|
const counters = {};
|
|
35
50
|
forEach(obj, (value, key) => {
|
|
36
51
|
const result = func(value, key);
|
|
37
|
-
counters
|
|
52
|
+
setOwn(counters, result, Object.hasOwn(counters, result) ? counters[result] + 1 : 1);
|
|
38
53
|
});
|
|
39
54
|
return counters;
|
|
40
55
|
}
|
|
@@ -54,6 +69,12 @@ export function find(arr, fn) {
|
|
|
54
69
|
if (Array.isArray(arr)) {
|
|
55
70
|
return arr.find(it);
|
|
56
71
|
}
|
|
72
|
+
else if (isIterable(arr)) {
|
|
73
|
+
for (const [index, value] of enumerate(arr)) {
|
|
74
|
+
if (it(value, index, arr))
|
|
75
|
+
return value;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
57
78
|
else if (isObject(arr)) {
|
|
58
79
|
for (const key of Object.keys(arr)) {
|
|
59
80
|
if (it(arr[key], key, arr)) {
|
|
@@ -94,17 +115,34 @@ filter(objects, matches({ a: 4, c: 6 }))
|
|
|
94
115
|
* @returns
|
|
95
116
|
*/
|
|
96
117
|
export function matches(shape) {
|
|
97
|
-
return
|
|
118
|
+
return (obj) => {
|
|
98
119
|
if (!shape || !obj)
|
|
99
120
|
return false;
|
|
121
|
+
const seen = new Map();
|
|
100
122
|
for (const key in shape) {
|
|
101
|
-
if (
|
|
123
|
+
if (!isPartialMatch(shape[key], obj[key], seen))
|
|
102
124
|
return false;
|
|
103
125
|
}
|
|
104
126
|
return true;
|
|
105
127
|
};
|
|
106
128
|
}
|
|
129
|
+
function isPartialMatch(shape, value, seen) {
|
|
130
|
+
if (shape === value)
|
|
131
|
+
return true;
|
|
132
|
+
const isList = Array.isArray(shape);
|
|
133
|
+
if (!isList && !isPlainObject(shape))
|
|
134
|
+
return false;
|
|
135
|
+
if (value === null || typeof value !== 'object' || isList !== Array.isArray(value))
|
|
136
|
+
return false;
|
|
137
|
+
const visited = seen.get(shape) ?? new Set();
|
|
138
|
+
if (visited.has(value))
|
|
139
|
+
return true;
|
|
140
|
+
seen.set(shape, visited.add(value));
|
|
141
|
+
return Object.keys(shape).every((key) => isPartialMatch(shape[key], value[key], seen));
|
|
142
|
+
}
|
|
107
143
|
export function forEach(collection, fn) {
|
|
144
|
+
if (collection == null)
|
|
145
|
+
return;
|
|
108
146
|
if (Array.isArray(collection)) {
|
|
109
147
|
for (let i = 0; i < collection.length; i++) {
|
|
110
148
|
const res = fn(collection[i], i, collection);
|
|
@@ -120,7 +158,7 @@ export function forEach(collection, fn) {
|
|
|
120
158
|
}
|
|
121
159
|
}
|
|
122
160
|
else {
|
|
123
|
-
for (const key of keys(collection)) {
|
|
161
|
+
for (const key of Object.keys(collection)) {
|
|
124
162
|
const res = fn(collection[key], key, collection);
|
|
125
163
|
if (res === false)
|
|
126
164
|
return;
|
|
@@ -129,7 +167,7 @@ export function forEach(collection, fn) {
|
|
|
129
167
|
}
|
|
130
168
|
export function findLast(arr, fn) {
|
|
131
169
|
let result;
|
|
132
|
-
const it = isFunction(fn) ? fn : matches(fn);
|
|
170
|
+
const it = isFunction(fn) ? fn : isObject(fn) ? matches(fn) : (obj) => get(fn, obj);
|
|
133
171
|
forEachRight(arr, (val, key) => {
|
|
134
172
|
if (it(val, key, arr)) {
|
|
135
173
|
result = val;
|
|
@@ -147,6 +185,14 @@ export function forEachRight(collection, fn) {
|
|
|
147
185
|
return;
|
|
148
186
|
}
|
|
149
187
|
}
|
|
188
|
+
else if (isIterable(collection)) {
|
|
189
|
+
const items = Array.from(collection);
|
|
190
|
+
for (let i = items.length - 1; i >= 0; i--) {
|
|
191
|
+
const res = fn(items[i], i, collection);
|
|
192
|
+
if (res === false)
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
150
196
|
else if (isObject(collection)) {
|
|
151
197
|
const keys = Object.keys(collection);
|
|
152
198
|
for (let i = keys.length - 1; i >= 0; i--) {
|
|
@@ -163,7 +209,7 @@ export function flatten(arr, depth = 1) {
|
|
|
163
209
|
return arr;
|
|
164
210
|
if (Array.isArray(arr))
|
|
165
211
|
return flattenArray(arr, depth, []);
|
|
166
|
-
if (
|
|
212
|
+
if (isFlattenable(arr))
|
|
167
213
|
return flattenObj(arr);
|
|
168
214
|
return arr;
|
|
169
215
|
}
|
|
@@ -178,15 +224,19 @@ function flattenArray(arr, depth = 1, result = []) {
|
|
|
178
224
|
}
|
|
179
225
|
return result;
|
|
180
226
|
}
|
|
227
|
+
/** A `Date` or `RegExp` has no keys to walk, so `flatten` keeps it as a leaf. */
|
|
228
|
+
function isFlattenable(x) {
|
|
229
|
+
return Array.isArray(x) || (isObject(x) && !isDate(x) && !isRegExp(x));
|
|
230
|
+
}
|
|
181
231
|
function flattenObj(obj, prefix = '', result = {}, keepNull = false) {
|
|
182
|
-
if (
|
|
183
|
-
result
|
|
232
|
+
if (isNull(obj) ? keepNull : !isFlattenable(obj)) {
|
|
233
|
+
setOwn(result, prefix, obj);
|
|
184
234
|
return result;
|
|
185
235
|
}
|
|
186
|
-
if (isArray(obj) || isObject(obj)) {
|
|
236
|
+
if (Array.isArray(obj) || isObject(obj)) {
|
|
187
237
|
for (const i of Object.keys(obj)) {
|
|
188
238
|
let pref = prefix;
|
|
189
|
-
if (isArray(obj)) {
|
|
239
|
+
if (Array.isArray(obj)) {
|
|
190
240
|
pref = `${pref}[${i}]`;
|
|
191
241
|
}
|
|
192
242
|
else {
|
|
@@ -208,6 +258,9 @@ export function map(arr, fn) {
|
|
|
208
258
|
if (Array.isArray(arr)) {
|
|
209
259
|
return arr.map((x, i) => it(x, i, arr));
|
|
210
260
|
}
|
|
261
|
+
if (isIterable(arr)) {
|
|
262
|
+
return Array.from(arr, (x, i) => it(x, i, arr));
|
|
263
|
+
}
|
|
211
264
|
if (isObject(arr)) {
|
|
212
265
|
return Object.keys(arr).map((key) => it(arr[key], key, arr));
|
|
213
266
|
}
|
|
@@ -219,13 +272,16 @@ export function pick(obj, paths) {
|
|
|
219
272
|
if (isFunction(paths)) {
|
|
220
273
|
for (const key of Object.keys(obj)) {
|
|
221
274
|
if (paths(obj[key], key)) {
|
|
222
|
-
result
|
|
275
|
+
setOwn(result, key, obj[key]);
|
|
223
276
|
}
|
|
224
277
|
}
|
|
225
278
|
return result;
|
|
226
279
|
}
|
|
227
|
-
for (const
|
|
228
|
-
|
|
280
|
+
for (const path of paths) {
|
|
281
|
+
const key = typeof path === 'symbol' ? path : String(path);
|
|
282
|
+
const value = get(path, obj);
|
|
283
|
+
if (key !== '__proto__' && (value !== undefined || key in Object(obj)))
|
|
284
|
+
result[key] = value;
|
|
229
285
|
}
|
|
230
286
|
return result;
|
|
231
287
|
}
|
|
@@ -236,16 +292,16 @@ export function omit(obj, paths) {
|
|
|
236
292
|
if (isFunction(paths)) {
|
|
237
293
|
for (const key of Object.keys(obj)) {
|
|
238
294
|
if (!paths(obj[key], key)) {
|
|
239
|
-
result
|
|
295
|
+
setOwn(result, key, obj[key]);
|
|
240
296
|
}
|
|
241
297
|
}
|
|
242
298
|
return result;
|
|
243
299
|
}
|
|
244
|
-
|
|
300
|
+
const kept = { ...obj };
|
|
245
301
|
for (const key of paths) {
|
|
246
|
-
delete
|
|
302
|
+
delete kept[key];
|
|
247
303
|
}
|
|
248
|
-
return
|
|
304
|
+
return kept;
|
|
249
305
|
}
|
|
250
306
|
export function findIndex(obj, fn, start = 0) {
|
|
251
307
|
if (!obj)
|
|
@@ -303,8 +359,7 @@ export function findLastIndex(arr, fn, start) {
|
|
|
303
359
|
if (arr == null)
|
|
304
360
|
return -1;
|
|
305
361
|
const length = arr.length;
|
|
306
|
-
|
|
307
|
-
start = length - 1;
|
|
362
|
+
start = Math.min(start ?? length - 1, length - 1);
|
|
308
363
|
if (!length || start < 0)
|
|
309
364
|
return -1;
|
|
310
365
|
const it = isFunction(fn) ? fn : isObject(fn) ? matches(fn) : (obj) => get(fn, obj);
|
|
@@ -335,12 +390,11 @@ lastIndexOf([1, 2, 1, 2], 2, 2)
|
|
|
335
390
|
export function lastIndexOf(obj, value, start) {
|
|
336
391
|
if (obj == null)
|
|
337
392
|
return -1;
|
|
338
|
-
const op = call(obj, 'lastIndexOf', value, start);
|
|
393
|
+
const op = call(obj, 'lastIndexOf', ...(start === undefined ? [value] : [value, start]));
|
|
339
394
|
if (op != null)
|
|
340
395
|
return op;
|
|
341
396
|
const length = obj.length;
|
|
342
|
-
|
|
343
|
-
start = length - 1;
|
|
397
|
+
start = Math.min(start ?? length - 1, length - 1);
|
|
344
398
|
if (!length || start < 0)
|
|
345
399
|
return -1;
|
|
346
400
|
for (; start >= 0; start--) {
|
|
@@ -350,29 +404,62 @@ export function lastIndexOf(obj, value, start) {
|
|
|
350
404
|
return -1;
|
|
351
405
|
}
|
|
352
406
|
export function clone(value, deep = false) {
|
|
353
|
-
|
|
407
|
+
return cloneValue(value, deep, new Map());
|
|
408
|
+
}
|
|
409
|
+
function cloneValue(value, deep, copies) {
|
|
410
|
+
if (copies.has(value))
|
|
411
|
+
return copies.get(value);
|
|
412
|
+
if (value instanceof ArrayBuffer)
|
|
413
|
+
return value.slice(0);
|
|
414
|
+
if (ArrayBuffer.isView(value)) {
|
|
354
415
|
return cloneTypedArray(value, deep);
|
|
355
416
|
}
|
|
356
|
-
if (
|
|
357
|
-
return
|
|
417
|
+
if (isObject(value) && isFunction(value.clone)) {
|
|
418
|
+
return value.clone();
|
|
419
|
+
}
|
|
420
|
+
if (Array.isArray(value) || hasElements(value)) {
|
|
421
|
+
return cloneArray(value, deep, copies);
|
|
422
|
+
}
|
|
423
|
+
if (value?.constructor === Map) {
|
|
424
|
+
const map = new Map();
|
|
425
|
+
copies.set(value, map);
|
|
426
|
+
for (const [key, item] of value)
|
|
427
|
+
map.set(key, deep ? cloneValue(item, deep, copies) : item);
|
|
428
|
+
return map;
|
|
429
|
+
}
|
|
430
|
+
if (value?.constructor === Set) {
|
|
431
|
+
const set = new Set();
|
|
432
|
+
copies.set(value, set);
|
|
433
|
+
for (const item of value)
|
|
434
|
+
set.add(deep ? cloneValue(item, deep, copies) : item);
|
|
435
|
+
return set;
|
|
358
436
|
}
|
|
359
437
|
if (isObject(value)) {
|
|
360
|
-
if (
|
|
361
|
-
return value.
|
|
438
|
+
if (isDate(value))
|
|
439
|
+
return new Date(value.getTime());
|
|
440
|
+
if (isRegExp(value)) {
|
|
441
|
+
const regex = new RegExp(value.source, value.flags);
|
|
442
|
+
regex.lastIndex = value.lastIndex;
|
|
443
|
+
return regex;
|
|
362
444
|
}
|
|
363
445
|
const copy = {};
|
|
446
|
+
copies.set(value, copy);
|
|
364
447
|
for (const key in value) {
|
|
365
448
|
if (deep) {
|
|
366
|
-
copy
|
|
449
|
+
setOwn(copy, key, cloneValue(value[key], deep, copies));
|
|
367
450
|
}
|
|
368
451
|
else {
|
|
369
|
-
copy
|
|
452
|
+
setOwn(copy, key, value[key]);
|
|
370
453
|
}
|
|
371
454
|
}
|
|
372
455
|
return copy;
|
|
373
456
|
}
|
|
374
457
|
return value;
|
|
375
458
|
}
|
|
459
|
+
/** `isArrayLike` accepts any numeric `length`, so this also looks for the elements. */
|
|
460
|
+
function hasElements(x) {
|
|
461
|
+
return isArrayLike(x) && (isIterable(x) || x.length - 1 in x);
|
|
462
|
+
}
|
|
376
463
|
/**
|
|
377
464
|
* Clones an array. If `deep` is `false` (default) the clone will be shallow. Otherwise {@link https://developer.mozilla.org/en-US/docs/Web/API/structuredClone structuredClone} is used.
|
|
378
465
|
* @param arr The array to clone
|
|
@@ -380,10 +467,20 @@ export function clone(value, deep = false) {
|
|
|
380
467
|
* @returns The new array
|
|
381
468
|
* @see {@link clone}
|
|
382
469
|
*/
|
|
383
|
-
|
|
470
|
+
function cloneArray(arr, deep, copies) {
|
|
384
471
|
if (!deep)
|
|
385
472
|
return Array.from(arr);
|
|
386
|
-
|
|
473
|
+
try {
|
|
474
|
+
return structuredClone(arr);
|
|
475
|
+
}
|
|
476
|
+
catch {
|
|
477
|
+
const copy = Array.from(arr);
|
|
478
|
+
copies.set(arr, copy);
|
|
479
|
+
copy.forEach((item, index) => {
|
|
480
|
+
copy[index] = cloneValue(item, deep, copies);
|
|
481
|
+
});
|
|
482
|
+
return copy;
|
|
483
|
+
}
|
|
387
484
|
}
|
|
388
485
|
/**
|
|
389
486
|
* Clones a typed array. If `deep` is `false` (default) the clone will be shallow. Otherwise {@link https://developer.mozilla.org/en-US/docs/Web/API/structuredClone structuredClone} is used.
|
|
@@ -392,40 +489,56 @@ export function cloneArray(arr, deep = false) {
|
|
|
392
489
|
* @returns The new array
|
|
393
490
|
* @see {@link clone}
|
|
394
491
|
*/
|
|
395
|
-
|
|
492
|
+
function cloneTypedArray(typedArray, isDeep = false) {
|
|
493
|
+
if (typedArray instanceof DataView) {
|
|
494
|
+
const viewed = isDeep ? typedArray.buffer.slice(0) : typedArray.buffer;
|
|
495
|
+
return new DataView(viewed, typedArray.byteOffset, typedArray.byteLength);
|
|
496
|
+
}
|
|
396
497
|
const buffer = isDeep ? structuredClone(typedArray) : typedArray.buffer;
|
|
397
498
|
return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length);
|
|
398
499
|
}
|
|
399
|
-
export function uniq(arr, fn =
|
|
500
|
+
export function uniq(arr, fn = identity) {
|
|
400
501
|
const keys = new Set();
|
|
502
|
+
const results = [];
|
|
401
503
|
const it = isFunction(fn) ? fn : (x) => get(fn, x);
|
|
402
|
-
for (const x of arr) {
|
|
403
|
-
|
|
504
|
+
for (const x of arr ?? []) {
|
|
505
|
+
const key = it(x);
|
|
506
|
+
if (keys.has(key))
|
|
507
|
+
continue;
|
|
508
|
+
keys.add(key);
|
|
509
|
+
results.push(Object.is(x, -0) ? 0 : x);
|
|
404
510
|
}
|
|
405
|
-
return
|
|
511
|
+
return results;
|
|
512
|
+
}
|
|
513
|
+
export function sortedUniq(arr, fn = identity) {
|
|
514
|
+
const it = isFunction(fn) ? fn : (x) => get(fn, x);
|
|
515
|
+
return uniq(arr, it).sort((x, y) => compare(it(x), it(y)));
|
|
406
516
|
}
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
517
|
+
/** True for an object made by `{}`, `JSON.parse` or `Object.create(null)`, in any realm. */
|
|
518
|
+
function isPlainObject(x) {
|
|
519
|
+
if (Object.prototype.toString.call(x) !== '[object Object]')
|
|
520
|
+
return false;
|
|
521
|
+
const proto = Object.getPrototypeOf(x);
|
|
522
|
+
return proto === null || Object.getPrototypeOf(proto) === null;
|
|
411
523
|
}
|
|
412
|
-
function baseMergeDeep(obj, source, key, stack) {
|
|
524
|
+
function baseMergeDeep(obj, source, key, stack, copies, merged) {
|
|
413
525
|
const objValue = obj[key];
|
|
414
526
|
const srcValue = source[key];
|
|
415
527
|
const stacked = stack.get(srcValue);
|
|
416
|
-
if (stacked
|
|
528
|
+
if (stacked) {
|
|
417
529
|
obj[key] = stacked;
|
|
418
530
|
return;
|
|
419
531
|
}
|
|
420
532
|
let newValue;
|
|
421
533
|
let isCommon = newValue === undefined;
|
|
534
|
+
let isCopy = false;
|
|
422
535
|
const isArray = Array.isArray(srcValue);
|
|
423
536
|
const isTyped = ArrayBuffer.isView(srcValue);
|
|
424
537
|
if (isArray || isTyped) {
|
|
425
538
|
if (Array.isArray(objValue)) {
|
|
426
539
|
newValue = objValue;
|
|
427
540
|
}
|
|
428
|
-
else if (
|
|
541
|
+
else if (hasElements(objValue)) {
|
|
429
542
|
newValue = Array.from(objValue);
|
|
430
543
|
}
|
|
431
544
|
else if (isTyped) {
|
|
@@ -434,42 +547,52 @@ function baseMergeDeep(obj, source, key, stack) {
|
|
|
434
547
|
}
|
|
435
548
|
else {
|
|
436
549
|
newValue = [];
|
|
550
|
+
isCopy = true;
|
|
437
551
|
}
|
|
438
552
|
}
|
|
439
|
-
else if (
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
newValue = srcValue;
|
|
443
|
-
}
|
|
553
|
+
else if (isPlainObject(srcValue)) {
|
|
554
|
+
isCopy = !isObject(objValue);
|
|
555
|
+
newValue = isCopy ? {} : objValue;
|
|
444
556
|
}
|
|
445
557
|
else {
|
|
446
558
|
isCommon = false;
|
|
559
|
+
newValue = srcValue;
|
|
447
560
|
}
|
|
448
|
-
if (
|
|
561
|
+
if (isCopy && copies.has(srcValue)) {
|
|
562
|
+
obj[key] = copies.get(srcValue);
|
|
563
|
+
return;
|
|
564
|
+
}
|
|
565
|
+
const targets = merged.get(srcValue) ?? new WeakSet();
|
|
566
|
+
if (isCommon && !targets.has(newValue)) {
|
|
567
|
+
merged.set(srcValue, targets.add(newValue));
|
|
449
568
|
stack.set(srcValue, newValue);
|
|
450
|
-
baseMerge(newValue, srcValue, stack);
|
|
569
|
+
baseMerge(newValue, srcValue, stack, copies, merged);
|
|
451
570
|
stack.delete(srcValue);
|
|
452
571
|
}
|
|
572
|
+
if (isCopy)
|
|
573
|
+
copies.set(srcValue, newValue);
|
|
453
574
|
obj[key] = newValue;
|
|
454
575
|
}
|
|
455
|
-
function baseMerge(obj, source, stack) {
|
|
576
|
+
function baseMerge(obj, source, stack, copies, merged) {
|
|
456
577
|
if (obj === source)
|
|
457
578
|
return obj;
|
|
458
579
|
for (const key of Object.keys(source)) {
|
|
580
|
+
if (key === '__proto__')
|
|
581
|
+
continue;
|
|
459
582
|
const srcValue = source[key];
|
|
460
583
|
const objValue = obj[key];
|
|
461
584
|
if (typeof srcValue === 'object' && srcValue !== null) {
|
|
462
|
-
baseMergeDeep(obj, source, key, stack
|
|
585
|
+
baseMergeDeep(obj, source, key, stack, copies, merged);
|
|
463
586
|
}
|
|
464
587
|
else {
|
|
465
|
-
if (objValue !== srcValue) {
|
|
588
|
+
if (srcValue !== undefined && objValue !== srcValue) {
|
|
466
589
|
obj[key] = srcValue;
|
|
467
590
|
}
|
|
468
591
|
}
|
|
469
592
|
}
|
|
470
593
|
}
|
|
471
594
|
/**
|
|
472
|
-
* Recursively merges own
|
|
595
|
+
* Recursively merges own enumerable string keyed properties of source objects into the destination object. Source properties that resolve to `undefined` are skipped if a destination value exists. Array and plain object properties are merged recursively. Other objects and value types are overridden by assignment. Source objects are applied from left to right. Subsequent sources overwrite property assignments of previous sources.
|
|
473
596
|
*
|
|
474
597
|
* Note: this method mutates `object`
|
|
475
598
|
*
|
|
@@ -494,7 +617,8 @@ merge(object, other)
|
|
|
494
617
|
*/
|
|
495
618
|
export function merge(object, ...sources) {
|
|
496
619
|
for (const source of sources) {
|
|
497
|
-
|
|
620
|
+
if (source != null)
|
|
621
|
+
baseMerge(object, source, new WeakMap(), new WeakMap(), new WeakMap());
|
|
498
622
|
}
|
|
499
623
|
return object;
|
|
500
624
|
}
|
|
@@ -534,11 +658,10 @@ export function defaults(object, ...sources) {
|
|
|
534
658
|
*/
|
|
535
659
|
export function* difference(...args) {
|
|
536
660
|
const sets = args.map((arr) => new Set(arr));
|
|
537
|
-
const setA = sets[0];
|
|
661
|
+
const setA = sets[0] ?? new Set();
|
|
538
662
|
for (let i = 1; i < sets.length; i++) {
|
|
539
663
|
for (const x of sets[i].values()) {
|
|
540
|
-
|
|
541
|
-
setA.add(x);
|
|
664
|
+
setA.delete(x);
|
|
542
665
|
}
|
|
543
666
|
}
|
|
544
667
|
for (const x of setA.values()) {
|
|
@@ -586,7 +709,7 @@ export function* intersection(...args) {
|
|
|
586
709
|
export function* union(...args) {
|
|
587
710
|
const results = new Set();
|
|
588
711
|
for (const arr of args) {
|
|
589
|
-
for (const item of arr) {
|
|
712
|
+
for (const item of arr ?? []) {
|
|
590
713
|
results.add(item);
|
|
591
714
|
}
|
|
592
715
|
}
|
|
@@ -594,18 +717,18 @@ export function* union(...args) {
|
|
|
594
717
|
yield item;
|
|
595
718
|
}
|
|
596
719
|
}
|
|
597
|
-
export function groupBy(arr, func =
|
|
720
|
+
export function groupBy(arr, func = identity) {
|
|
598
721
|
const useKey = isFunction(func) ? func : (obj) => get(func, obj);
|
|
599
722
|
const results = {};
|
|
600
723
|
forEach(arr, (value) => {
|
|
601
724
|
const groupKey = useKey(value);
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
results[groupKey]
|
|
725
|
+
if (!Object.hasOwn(results, groupKey))
|
|
726
|
+
setOwn(results, groupKey, []);
|
|
727
|
+
results[groupKey].push(value);
|
|
605
728
|
});
|
|
606
729
|
return results;
|
|
607
730
|
}
|
|
608
|
-
export function groupByMap(arr, func =
|
|
731
|
+
export function groupByMap(arr, func = identity) {
|
|
609
732
|
const results = new Map();
|
|
610
733
|
const useKey = isFunction(func) ? func : (obj) => get(func, obj);
|
|
611
734
|
forEach(arr, (value) => {
|
|
@@ -617,13 +740,17 @@ export function groupByMap(arr, func = id) {
|
|
|
617
740
|
return results;
|
|
618
741
|
}
|
|
619
742
|
export function remove(arr, func) {
|
|
620
|
-
const it = isFunction(func)
|
|
743
|
+
const it = isFunction(func)
|
|
744
|
+
? func
|
|
745
|
+
: Array.isArray(func)
|
|
746
|
+
? (x) => func.includes(x)
|
|
747
|
+
: (x) => func === x;
|
|
621
748
|
return arr.filter((x, i) => !it(x, i, arr));
|
|
622
749
|
}
|
|
623
750
|
/**
|
|
624
751
|
* Returns the index of `x` in a **sorted** array if found, in `O(log n)` using binary search.
|
|
625
|
-
* If the element is not found, returns
|
|
626
|
-
* @param arr The array
|
|
752
|
+
* If the element is not found, returns `-n - 1`, where `n` is the index to insert `x` at.
|
|
753
|
+
* @param arr The sorted array
|
|
627
754
|
* @param x The element to find
|
|
628
755
|
* @param lo The starting index
|
|
629
756
|
* @param hi The end index to search within
|
|
@@ -631,7 +758,7 @@ export function remove(arr, func) {
|
|
|
631
758
|
* @returns {number} The index if the element is found or a negative integer.
|
|
632
759
|
*/
|
|
633
760
|
export function binarySearch(arr, x, lo = 0, hi, comp = compare) {
|
|
634
|
-
hi
|
|
761
|
+
hi ??= arr.length - 1;
|
|
635
762
|
while (lo < hi) {
|
|
636
763
|
const mid = (lo + hi) >> 1;
|
|
637
764
|
const check = comp(x, arr[mid]);
|
|
@@ -642,14 +769,15 @@ export function binarySearch(arr, x, lo = 0, hi, comp = compare) {
|
|
|
642
769
|
else
|
|
643
770
|
hi = mid - 1;
|
|
644
771
|
}
|
|
645
|
-
|
|
772
|
+
const check = lo <= hi ? comp(x, arr[lo]) : -1;
|
|
773
|
+
if (check === 0)
|
|
646
774
|
return lo;
|
|
647
|
-
// Returns (-
|
|
648
|
-
return -lo - 1;
|
|
775
|
+
// Returns (-n - 1) where n is the insertion point for new element in the range
|
|
776
|
+
return check > 0 ? -lo - 2 : -lo - 1;
|
|
649
777
|
}
|
|
650
778
|
/**
|
|
651
779
|
* Returns an insertion index which comes after any existing entries of `x` in a **sorted** array, using binary search.
|
|
652
|
-
* @param arr The array
|
|
780
|
+
* @param arr The sorted array
|
|
653
781
|
* @param x The element to find
|
|
654
782
|
* @param lo The starting index
|
|
655
783
|
* @param hi The end index to search within
|
|
@@ -657,20 +785,20 @@ export function binarySearch(arr, x, lo = 0, hi, comp = compare) {
|
|
|
657
785
|
* @returns {number}
|
|
658
786
|
*/
|
|
659
787
|
export function bisect(arr, x, lo = 0, hi, comp = compare) {
|
|
660
|
-
hi
|
|
788
|
+
hi ??= arr.length;
|
|
661
789
|
while (lo < hi) {
|
|
662
790
|
const mid = (lo + hi) >> 1;
|
|
663
791
|
const check = comp(x, arr[mid]);
|
|
664
792
|
if (check >= 0)
|
|
665
793
|
lo = mid + 1;
|
|
666
794
|
else
|
|
667
|
-
hi = mid
|
|
795
|
+
hi = mid;
|
|
668
796
|
}
|
|
669
797
|
return lo;
|
|
670
798
|
}
|
|
671
799
|
/**
|
|
672
800
|
* Returns an insertion index which comes before any existing entries of `x` in a **sorted** array, using binary search.
|
|
673
|
-
* @param arr The array
|
|
801
|
+
* @param arr The sorted array
|
|
674
802
|
* @param x The element to find
|
|
675
803
|
* @param lo The starting index
|
|
676
804
|
* @param hi The end index to search within
|
|
@@ -678,12 +806,12 @@ export function bisect(arr, x, lo = 0, hi, comp = compare) {
|
|
|
678
806
|
* @returns {number}
|
|
679
807
|
*/
|
|
680
808
|
export function bisectLeft(arr, x, lo = 0, hi, comp = compare) {
|
|
681
|
-
hi
|
|
809
|
+
hi ??= arr.length;
|
|
682
810
|
while (lo < hi) {
|
|
683
811
|
const mid = (lo + hi) >> 1;
|
|
684
812
|
const check = comp(x, arr[mid]);
|
|
685
813
|
if (check <= 0)
|
|
686
|
-
hi = mid
|
|
814
|
+
hi = mid;
|
|
687
815
|
else
|
|
688
816
|
lo = mid + 1;
|
|
689
817
|
}
|
package/dist/decimal/index.d.ts
CHANGED
|
@@ -20,6 +20,8 @@ export declare class Decimal {
|
|
|
20
20
|
* Returns a new `Decimal` instance from the value or `0`.
|
|
21
21
|
* @param {*} value
|
|
22
22
|
* @returns {Decimal}
|
|
23
|
+
* @throws {ValueError} if the value is not numeric.
|
|
24
|
+
* @throws {RangeError} if the value is infinite or its exponent is past 10,000.
|
|
23
25
|
*/
|
|
24
26
|
constructor(value?: any);
|
|
25
27
|
/**
|
|
@@ -75,14 +77,15 @@ export declare class Decimal {
|
|
|
75
77
|
```js
|
|
76
78
|
let a = decimal('1')
|
|
77
79
|
let b = decimal('3')
|
|
78
|
-
a.div(b) // 0.
|
|
80
|
+
a.div(b) // 0.33333333333333333333
|
|
79
81
|
```
|
|
80
82
|
* @returns {Decimal}
|
|
81
83
|
*/
|
|
82
84
|
div(x: Decimal | string | number): Decimal;
|
|
83
85
|
/**
|
|
84
86
|
* Returns the square root of this `Decimal`.
|
|
85
|
-
* @returns {
|
|
87
|
+
* @returns {Decimal}
|
|
88
|
+
* @throws {ValueError} if this value is negative.
|
|
86
89
|
*/
|
|
87
90
|
sqrt(): Decimal;
|
|
88
91
|
/** Returns a new copy of this Decimal value. */
|