atomic-fns 0.2.0 → 0.2.2

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.
@@ -1,5 +1,24 @@
1
- import { call, get, isArray, isArrayLike, isBool, isEmpty, isFunc, isNull, isNumber, isObject, isString, keys, NotImplementedError, set } from './globals.js';
2
- import { comp, eq, id } from './operators.js';
1
+ /**
2
+ * Collections
3
+ * @module
4
+ */
5
+ import {
6
+ call,
7
+ get,
8
+ isArray,
9
+ isArrayLike,
10
+ isBool,
11
+ isEmpty,
12
+ isFunc,
13
+ isNull,
14
+ isNumber,
15
+ isObject,
16
+ isString,
17
+ keys,
18
+ NotImplementedError,
19
+ set
20
+ } from './globals.js'
21
+ import { comp, eq, id } from './operators.js'
3
22
  /**
4
23
  * A Collection is an iterable container type.
5
24
  * This is an abstract base class for user-defined collection types.
@@ -10,49 +29,52 @@ import { comp, eq, id } from './operators.js';
10
29
  * @implements {Container}
11
30
  */
12
31
  export class Collection {
13
- /**
14
- * Returns an iterator for the container items
15
- * @return {Iterator}
16
- */
17
- [Symbol.iterator]() {
18
- return this;
19
- }
20
- /**
21
- * Implements the iterator protocol and returns the next item in the iterable.
22
- */
23
- next() { }
24
- /**
25
- * Adds a new item to the container.
26
- * @param item
27
- */
28
- add(item) { }
29
- /**
30
- * Checks if item is present in the container.
31
- * @param item
32
- */
33
- contains(item) {
34
- return false;
35
- }
36
- /**
37
- * Returns the total number of elements in the container.
38
- */
39
- size() {
40
- throw new NotImplementedError();
41
- }
42
- /**
43
- * Remove the first item from the container where `item == x`
44
- * @raises ValueError when x is not found
45
- */
46
- remove(x) { }
47
- /**
48
- * Retrieve and remove the item at index `i`.
49
- * @returns the item or undefined if not found.
50
- */
51
- pop(i) { }
52
- /**
53
- * Remove all items from the container
54
- */
55
- clear() { }
32
+ /**
33
+ * Returns an iterator for the container items
34
+ * @return {Iterator}
35
+ */
36
+ [Symbol.iterator]() {
37
+ return this
38
+ }
39
+
40
+ /**
41
+ * Implements the iterator protocol and returns the next item in the iterable.
42
+ */
43
+ next() {}
44
+ /**
45
+ * Adds a new item to the container.
46
+ * @param item
47
+ */
48
+ add(item) {}
49
+ /**
50
+ * Checks if item is present in the container.
51
+ * @param item
52
+ */
53
+ contains(item) {
54
+ return false
55
+ }
56
+
57
+ /**
58
+ * Returns the total number of elements in the container.
59
+ */
60
+ size() {
61
+ throw new NotImplementedError()
62
+ }
63
+
64
+ /**
65
+ * Remove the first item from the container where `item == x`
66
+ * @raises ValueError when x is not found
67
+ */
68
+ remove(x) {}
69
+ /**
70
+ * Retrieve and remove the item at index `i`.
71
+ * @returns the item or undefined if not found.
72
+ */
73
+ pop(i) {}
74
+ /**
75
+ * Remove all items from the container
76
+ */
77
+ clear() {}
56
78
  }
57
79
  /**
58
80
  * A sequence is an iterable type with efficient index-based access.
@@ -64,64 +86,69 @@ export class Collection {
64
86
  * @template T
65
87
  */
66
88
  export class Sequence extends Collection {
67
- /**
68
- * Return the item at the given key or index
69
- * @param {*} key
70
- * @memberof Sequence
71
- */
72
- get(key) {
73
- throw new NotImplementedError();
74
- }
75
- /**
76
- * Set a new value at the given key or index
77
- *
78
- * @param {*} key
79
- * @param {T} val
80
- * @memberof Sequence
81
- */
82
- set(key, val) {
83
- throw new NotImplementedError();
84
- }
85
- /**
86
- * Deletes the given key or index, and its value.
87
- * Raises ValueError if not key is found.
88
- *
89
- * @param {*} key
90
- * @memberof Sequence
91
- */
92
- delete(key) {
93
- throw new NotImplementedError();
94
- }
95
- /**
96
- * Adds a new item to the end of the sequence.
97
- *
98
- * @param {T} x
99
- * @memberof Sequence
100
- */
101
- append(x) { }
102
- /**
103
- * Append all the items to the sequence.
104
- *
105
- * @param {Iterable<T>} iter
106
- * @memberof Sequence
107
- */
108
- extend(iter) { }
109
- /**
110
- * Return the index of x in the sequence, or undefined if not found.
111
- *
112
- * @param {T} item
113
- * @return {(number | undefined)}
114
- * @memberof Sequence
115
- */
116
- indexOf(item) {
117
- throw new NotImplementedError();
118
- }
119
- size() {
120
- return 0;
121
- }
122
- reversed() {
123
- throw new NotImplementedError();
124
- }
89
+ /**
90
+ * Return the item at the given key or index
91
+ * @param {*} key
92
+ * @memberof Sequence
93
+ */
94
+ get(key) {
95
+ throw new NotImplementedError()
96
+ }
97
+
98
+ /**
99
+ * Set a new value at the given key or index
100
+ *
101
+ * @param {*} key
102
+ * @param {T} val
103
+ * @memberof Sequence
104
+ */
105
+ set(key, val) {
106
+ throw new NotImplementedError()
107
+ }
108
+
109
+ /**
110
+ * Deletes the given key or index, and its value.
111
+ * Raises ValueError if not key is found.
112
+ *
113
+ * @param {*} key
114
+ * @memberof Sequence
115
+ */
116
+ delete(key) {
117
+ throw new NotImplementedError()
118
+ }
119
+
120
+ /**
121
+ * Adds a new item to the end of the sequence.
122
+ *
123
+ * @param {T} x
124
+ * @memberof Sequence
125
+ */
126
+ append(x) {}
127
+ /**
128
+ * Append all the items to the sequence.
129
+ *
130
+ * @param {Iterable<T>} iter
131
+ * @memberof Sequence
132
+ */
133
+ extend(iter) {}
134
+ /**
135
+ * Return the index of x in the sequence, or undefined if not found.
136
+ *
137
+ * @param {T} item
138
+ * @return {(number | undefined)}
139
+ * @memberof Sequence
140
+ */
141
+ indexOf(item) {
142
+ throw new NotImplementedError()
143
+ }
144
+
145
+ size() {
146
+ return 0
147
+ }
148
+
149
+ reversed() {
150
+ throw new NotImplementedError()
151
+ }
125
152
  }
126
153
  /**
127
154
  * Returns a new immutable Set object with elements from `iterable`. Its contents cannot be altered after it's created.
@@ -132,27 +159,31 @@ export class Sequence extends Collection {
132
159
  * @template T
133
160
  */
134
161
  export class FrozenSet extends Set {
135
- constructor(iterable) {
136
- super(iterable);
137
- return this.freeze();
138
- }
139
- add() {
140
- throw TypeError('FrozenSet cannot be modified.');
162
+ constructor(iterable) {
163
+ super(iterable)
164
+ return this.freeze()
165
+ }
166
+
167
+ add() {
168
+ throw TypeError('FrozenSet cannot be modified.')
141
169
  return this; // eslint-disable-line
142
- }
143
- delete() {
144
- throw TypeError('FrozenSet cannot be modified.');
170
+ }
171
+
172
+ delete() {
173
+ throw TypeError('FrozenSet cannot be modified.')
145
174
  return false; // eslint-disable-line
146
- }
147
- clear() {
148
- throw TypeError('FrozenSet cannot be modified.');
175
+ }
176
+
177
+ clear() {
178
+ throw TypeError('FrozenSet cannot be modified.')
149
179
  return this; // eslint-disable-line
150
- }
151
- freeze() {
152
- return Object.freeze(this);
153
- }
180
+ }
181
+
182
+ freeze() {
183
+ return Object.freeze(this)
184
+ }
154
185
  }
155
- export const compact = (...arr) => arr.filter((x) => !isEmpty(x));
186
+ export const compact = (...arr) => arr.filter((x) => !isEmpty(x))
156
187
  /**
157
188
  * Creates a function that can be used to create named tuple-like objects.
158
189
  * @example
@@ -167,198 +198,163 @@ export const compact = (...arr) => arr.filter((x) => !isEmpty(x));
167
198
  * @return
168
199
  */
169
200
  export function namedtuple(...fields) {
170
- return (...args) => fields.reduce((prev, f, i) => set(prev, f, args[i], false, true), {});
201
+ return (...args) => fields.reduce((prev, f, i) => set(prev, f, args[i], false, true), {})
171
202
  }
172
203
  export function filter(arr, fn = isNull) {
173
- if (Array.isArray(arr)) {
174
- // @ts-expect-error function is not compatible?
175
- if (typeof fn === 'function')
176
- return arr.filter(fn);
177
- if (typeof fn === 'string')
178
- return arr.filter((x) => get(x, fn));
179
- if (isObject(fn))
180
- return arr.filter(matches(fn));
181
- }
204
+ if (Array.isArray(arr)) {
205
+ // @ts-expect-error function is not compatible?
206
+ if (typeof fn === 'function') return arr.filter(fn)
207
+ if (typeof fn === 'string') return arr.filter((x) => get(x, fn))
208
+ if (isObject(fn)) return arr.filter(matches(fn))
209
+ }
182
210
  }
183
211
  export function find(arr, fn) {
184
- if (Array.isArray(arr)) {
185
- if (typeof fn === 'function')
186
- return arr.find(fn);
187
- if (typeof fn === 'string')
188
- return arr.find((x) => x && x[fn]);
189
- if (isObject(fn))
190
- return arr.find(matches(fn));
191
- }
212
+ if (Array.isArray(arr)) {
213
+ if (typeof fn === 'function') return arr.find(fn)
214
+ if (typeof fn === 'string') return arr.find((x) => x?.[fn])
215
+ if (isObject(fn)) return arr.find(matches(fn))
216
+ }
192
217
  }
193
218
  export function findRight(arr, fn) {
194
- if (Array.isArray(arr)) {
195
- for (let i = arr.length - 1; i >= 0; i--) {
196
- const x = arr[i];
197
- if (typeof fn === 'function') {
198
- if (fn(x))
199
- return x;
200
- }
201
- else if (typeof fn === 'string') {
202
- if (x && x[fn])
203
- return x;
204
- }
205
- else if (isObject(fn)) {
206
- if (matches(fn)(x))
207
- return x;
208
- }
209
- }
210
- }
219
+ if (Array.isArray(arr)) {
220
+ for (let i = arr.length - 1; i >= 0; i--) {
221
+ const x = arr[i]
222
+ if (typeof fn === 'function') {
223
+ if (fn(x)) return x
224
+ } else if (typeof fn === 'string') {
225
+ if (x?.[fn]) return x
226
+ } else if (isObject(fn)) {
227
+ if (matches(fn)(x)) return x
228
+ }
229
+ }
230
+ }
211
231
  }
212
232
  export const matches = (o) => (x) => {
213
- if (!o || !x)
214
- return false;
215
- for (const key in o) {
216
- if (!eq(x[key], o[key]))
217
- return false;
218
- }
219
- return true;
220
- };
233
+ if (!o || !x) return false
234
+ for (const key in o) {
235
+ if (!eq(x[key], o[key])) return false
236
+ }
237
+ return true
238
+ }
221
239
  export function forEach(arr, fn) {
222
- if (Array.isArray(arr))
223
- return arr.forEach(fn);
224
- if (isObject(arr)) {
225
- return Object.keys(arr).forEach((key) => fn(get(arr, key), key, arr));
226
- }
240
+ if (Array.isArray(arr)) return arr.forEach(fn)
241
+ if (isObject(arr)) {
242
+ return Object.keys(arr).forEach((key) => fn(get(arr, key), key, arr))
243
+ }
227
244
  }
228
245
  export function flatten(arr, depth = 1) {
229
- if (!depth)
230
- return arr;
231
- if (Array.isArray(arr))
232
- return flattenArray(arr, depth, []);
233
- if (isObject(arr))
234
- return flattenObj(arr);
235
- return arr;
246
+ if (!depth) return arr
247
+ if (Array.isArray(arr)) return flattenArray(arr, depth, [])
248
+ if (isObject(arr)) return flattenObj(arr)
249
+ return arr
236
250
  }
237
251
  export function flattenArray(arr, depth = 1, result = []) {
238
- for (const value of arr) {
239
- if (depth && Array.isArray(value)) {
240
- flattenArray(value, typeof depth === 'number' ? depth - 1 : depth, result);
241
- }
242
- else {
243
- result.push(value);
244
- }
245
- }
246
- return result;
252
+ for (const value of arr) {
253
+ if (depth && Array.isArray(value)) {
254
+ flattenArray(value, typeof depth === 'number' ? depth - 1 : depth, result)
255
+ } else {
256
+ result.push(value)
257
+ }
258
+ }
259
+ return result
247
260
  }
248
261
  export function flattenObj(o, prefix = '', result = {}, keepNull = false) {
249
- if (isString(o) || isNumber(o) || isBool(o) || (keepNull && isNull(o))) {
250
- result[prefix] = o;
251
- return result;
252
- }
253
- if (isArray(o) || isObject(o)) {
254
- for (const i in o) {
255
- let pref = prefix;
256
- if (isArray(o)) {
257
- pref = pref + `[${i}]`;
258
- }
259
- else {
260
- if (isEmpty(prefix)) {
261
- pref = i;
262
- }
263
- else {
264
- pref = prefix + '.' + i;
265
- }
266
- }
267
- flattenObj(o[i], pref, result, keepNull);
262
+ if (isString(o) || isNumber(o) || isBool(o) || (keepNull && isNull(o))) {
263
+ result[prefix] = o
264
+ return result
265
+ }
266
+ if (isArray(o) || isObject(o)) {
267
+ for (const i in o) {
268
+ let pref = prefix
269
+ if (isArray(o)) {
270
+ pref = pref + `[${i}]`
271
+ } else {
272
+ if (isEmpty(prefix)) {
273
+ pref = i
274
+ } else {
275
+ pref = prefix + '.' + i
268
276
  }
269
- return result;
277
+ }
278
+ flattenObj(o[i], pref, result, keepNull)
270
279
  }
271
- return result;
280
+ return result
281
+ }
282
+ return result
272
283
  }
273
284
  export const map = (arr, fn) => {
274
- if (Array.isArray(arr)) {
275
- return arr.map((x, i) => {
276
- if (typeof fn === 'string')
277
- return x[fn];
278
- return fn(x, i, arr);
279
- });
280
- }
281
- if (isObject(arr)) {
282
- return Object.keys(arr).map((key) => {
283
- if (typeof fn === 'string')
284
- return get(arr[key], fn);
285
- return fn(arr[key], key, arr);
286
- });
287
- }
288
- };
285
+ if (Array.isArray(arr)) {
286
+ return arr.map((x, i) => {
287
+ if (typeof fn === 'string') return x[fn]
288
+ return fn(x, i, arr)
289
+ })
290
+ }
291
+ if (isObject(arr)) {
292
+ return Object.keys(arr).map((key) => {
293
+ if (typeof fn === 'string') return get(arr[key], fn)
294
+ return fn(arr[key], key, arr)
295
+ })
296
+ }
297
+ }
289
298
  export function pick(obj, paths) {
290
- if (obj == null) {
291
- return {};
292
- }
293
- const result = {};
294
- if (Array.isArray(paths)) {
295
- for (const key of paths) {
296
- result[key] = obj[key];
297
- }
298
- return result;
299
- }
300
- else if (typeof paths === 'function') {
301
- for (const key in obj) {
302
- const value = obj[key];
303
- if (paths(value, key))
304
- result[key] = value;
305
- }
299
+ if (obj == null) {
300
+ return {}
301
+ }
302
+ const result = {}
303
+ if (Array.isArray(paths)) {
304
+ for (const key of paths) {
305
+ result[key] = obj[key]
306
+ }
307
+ return result
308
+ } else if (typeof paths === 'function') {
309
+ for (const key in obj) {
310
+ const value = obj[key]
311
+ if (paths(value, key)) result[key] = value
306
312
  }
307
- return result;
313
+ }
314
+ return result
308
315
  }
309
316
  export function omit(obj, paths) {
310
- const result = {};
311
- for (const key in obj) {
312
- const value = obj[key];
313
- if (Array.isArray(paths) && !paths.includes(key)) {
314
- result[key] = value;
315
- }
316
- else if (typeof paths === 'function' && !paths(value, key)) {
317
- result[key] = value;
318
- }
319
- }
320
- return result;
317
+ const result = {}
318
+ for (const key in obj) {
319
+ const value = obj[key]
320
+ if (Array.isArray(paths) && !paths.includes(key)) {
321
+ result[key] = value
322
+ } else if (typeof paths === 'function' && !paths(value, key)) {
323
+ result[key] = value
324
+ }
325
+ }
326
+ return result
321
327
  }
322
328
  export function contains(arr, y) {
323
- const op = call(arr, 'contains', y);
324
- if (op != null)
325
- return op;
326
- return indexOf(arr, y) >= 0;
329
+ const op = call(arr, 'contains', y)
330
+ if (op != null) return op
331
+ return indexOf(arr, y) >= 0
327
332
  }
328
333
  export function indexOf(obj, x, start = 0) {
329
- if (obj == null)
330
- return;
331
- const op = call(obj, 'indexOf', x, start);
332
- if (op != null)
333
- return op;
334
- const length = obj.length;
335
- if (length && start < 0) {
336
- start = Math.max(start + length, 0);
337
- }
338
- if (!length || start >= length)
339
- return -1;
340
- for (; start < length; start++) {
341
- if (eq(x, obj[start]))
342
- return start;
343
- }
344
- return -1;
334
+ if (obj == null) return
335
+ const op = call(obj, 'indexOf', x, start)
336
+ if (op != null) return op
337
+ const length = obj.length
338
+ if (length && start < 0) {
339
+ start = Math.max(start + length, 0)
340
+ }
341
+ if (!length || start >= length) return -1
342
+ for (; start < length; start++) {
343
+ if (eq(x, obj[start])) return start
344
+ }
345
+ return -1
345
346
  }
346
347
  export function lastIndexOf(obj, x, start) {
347
- if (obj == null)
348
- return;
349
- const op = call(obj, 'lastIndexOf', x, start);
350
- if (op != null)
351
- return op;
352
- const length = obj.length;
353
- if (start == null)
354
- start = length - 1;
355
- if (!length || start < 0)
356
- return -1;
357
- for (; start >= 0; start--) {
358
- if (eq(x, obj[start]))
359
- return start;
360
- }
361
- return -1;
348
+ if (obj == null) return
349
+ const op = call(obj, 'lastIndexOf', x, start)
350
+ if (op != null) return op
351
+ const length = obj.length
352
+ if (start == null) start = length - 1
353
+ if (!length || start < 0) return -1
354
+ for (; start >= 0; start--) {
355
+ if (eq(x, obj[start])) return start
356
+ }
357
+ return -1
362
358
  }
363
359
  /**
364
360
  * Creates a clone of the given `obj`. If `deep` is `true` it will clone it recursively.
@@ -369,118 +365,108 @@ export function lastIndexOf(obj, x, start) {
369
365
  * @return The clone value
370
366
  */
371
367
  export function clone(obj, deep = false) {
372
- if (ArrayBuffer.isView(obj)) {
373
- return cloneTypedArray(obj, deep);
374
- }
375
- if (isArray(obj) || isArrayLike(obj)) {
376
- return cloneArray(obj, deep);
377
- }
378
- if (isObject(obj)) {
379
- if (isFunc(obj.clone)) {
380
- return obj.clone();
381
- }
382
- const copy = {};
383
- for (const key of keys(obj)) {
384
- if (deep) {
385
- copy[key] = clone(obj[key], deep);
386
- }
387
- else {
388
- copy[key] = obj[key];
389
- }
390
- }
391
- return copy;
392
- }
393
- return obj;
368
+ if (ArrayBuffer.isView(obj)) {
369
+ return cloneTypedArray(obj, deep)
370
+ }
371
+ if (isArray(obj) || isArrayLike(obj)) {
372
+ return cloneArray(obj, deep)
373
+ }
374
+ if (isObject(obj)) {
375
+ if (isFunc(obj.clone)) {
376
+ return obj.clone()
377
+ }
378
+ const copy = {}
379
+ for (const key of keys(obj)) {
380
+ if (deep) {
381
+ copy[key] = clone(obj[key], deep)
382
+ } else {
383
+ copy[key] = obj[key]
384
+ }
385
+ }
386
+ return copy
387
+ }
388
+ return obj
394
389
  }
395
390
  export function cloneArray(arr, deep = false) {
396
- if (!deep)
397
- return Array.from(arr);
398
- return arr.map((item) => clone(item, deep));
391
+ if (!deep) return Array.from(arr)
392
+ return arr.map((item) => clone(item, deep))
399
393
  }
400
394
  export function cloneArrayBuffer(arrayBuffer) {
401
- const result = new arrayBuffer.constructor(arrayBuffer.byteLength);
402
- new Uint8Array(result).set(new Uint8Array(arrayBuffer));
403
- return result;
395
+ const result = new arrayBuffer.constructor(arrayBuffer.byteLength)
396
+ new Uint8Array(result).set(new Uint8Array(arrayBuffer))
397
+ return result
404
398
  }
405
399
  export function cloneTypedArray(typedArray, isDeep) {
406
- const buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer;
407
- return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length);
400
+ const buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer
401
+ return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length)
408
402
  }
409
403
  export function uniq(arr, fn = id) {
410
- const keys = new Set();
411
- for (const x of arr) {
412
- if (typeof fn === 'function') {
413
- keys.add(fn(x));
414
- }
415
- else {
416
- keys.add(get(x, fn));
417
- }
418
- }
419
- return Array.from(keys.values());
404
+ const keys = new Set()
405
+ for (const x of arr) {
406
+ if (typeof fn === 'function') {
407
+ keys.add(fn(x))
408
+ } else {
409
+ keys.add(get(x, fn))
410
+ }
411
+ }
412
+ return Array.from(keys.values())
420
413
  }
421
414
  export function sortedUniq(arr, fn = id) {
422
- const lst = uniq(arr, fn);
423
- lst.sort(comp);
424
- return lst;
415
+ const lst = uniq(arr, fn)
416
+ lst.sort(comp)
417
+ return lst
425
418
  }
426
419
  function baseMergeDeep(obj, source, key, stack) {
427
- const objValue = obj[key];
428
- const srcValue = source[key];
429
- const stacked = stack.get(srcValue);
430
- if (stacked && (objValue !== stacked || !(key in obj))) {
431
- obj[key] = stacked;
432
- return;
433
- }
434
- let newValue;
435
- let isCommon = newValue === undefined;
436
- const isArray = Array.isArray(srcValue);
437
- const isTyped = ArrayBuffer.isView(srcValue);
438
- if (isArray || isTyped) {
439
- if (Array.isArray(objValue)) {
440
- newValue = objValue;
441
- }
442
- else if (isArrayLike(objValue)) {
443
- newValue = Array.from(objValue);
444
- }
445
- else if (isTyped) {
446
- isCommon = false;
447
- newValue = cloneTypedArray(srcValue, true);
448
- }
449
- else {
450
- newValue = [];
451
- }
452
- }
453
- else if (isObject(srcValue)) {
454
- newValue = objValue;
455
- if (!isObject(objValue)) {
456
- newValue = srcValue;
457
- }
458
- }
459
- else {
460
- isCommon = false;
461
- }
462
- if (isCommon) {
463
- stack.set(srcValue, newValue);
464
- baseMerge(newValue, srcValue, stack);
465
- stack.delete(srcValue);
466
- }
467
- obj[key] = newValue;
420
+ const objValue = obj[key]
421
+ const srcValue = source[key]
422
+ const stacked = stack.get(srcValue)
423
+ if (stacked && (objValue !== stacked || !(key in obj))) {
424
+ obj[key] = stacked
425
+ return
426
+ }
427
+ let newValue
428
+ let isCommon = newValue === undefined
429
+ const isArray = Array.isArray(srcValue)
430
+ const isTyped = ArrayBuffer.isView(srcValue)
431
+ if (isArray || isTyped) {
432
+ if (Array.isArray(objValue)) {
433
+ newValue = objValue
434
+ } else if (isArrayLike(objValue)) {
435
+ newValue = Array.from(objValue)
436
+ } else if (isTyped) {
437
+ isCommon = false
438
+ newValue = cloneTypedArray(srcValue, true)
439
+ } else {
440
+ newValue = []
441
+ }
442
+ } else if (isObject(srcValue)) {
443
+ newValue = objValue
444
+ if (!isObject(objValue)) {
445
+ newValue = srcValue
446
+ }
447
+ } else {
448
+ isCommon = false
449
+ }
450
+ if (isCommon) {
451
+ stack.set(srcValue, newValue)
452
+ baseMerge(newValue, srcValue, stack)
453
+ stack.delete(srcValue)
454
+ }
455
+ obj[key] = newValue
468
456
  }
469
457
  function baseMerge(obj, source, stack) {
470
- if (obj === source)
471
- return obj;
472
- for (const key in source) {
473
- const srcValue = source[key];
474
- const objValue = obj[key];
475
- if (typeof srcValue === 'object' && srcValue !== null) {
476
- baseMergeDeep(obj, source, key, stack || new WeakMap());
477
- }
478
- else {
479
- if (objValue !== srcValue) {
480
- obj[key] = srcValue;
481
- }
482
- }
483
- }
458
+ if (obj === source) return obj
459
+ for (const key in source) {
460
+ const srcValue = source[key]
461
+ const objValue = obj[key]
462
+ if (typeof srcValue === 'object' && srcValue !== null) {
463
+ baseMergeDeep(obj, source, key, stack || new WeakMap())
464
+ } else {
465
+ if (objValue !== srcValue) {
466
+ obj[key] = srcValue
467
+ }
468
+ }
469
+ }
484
470
  }
485
471
  /**
486
472
  * Recursively merges own and inherited 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.
@@ -493,50 +479,48 @@ function baseMerge(obj, source, stack) {
493
479
  * @return {Object} The destination object.
494
480
  */
495
481
  export function merge(obj, ...sources) {
496
- for (const source of sources) {
497
- baseMerge(obj, source);
498
- }
499
- return obj;
482
+ for (const source of sources) {
483
+ baseMerge(obj, source)
484
+ }
485
+ return obj
500
486
  }
501
487
  export function* difference(...args) {
502
- const sets = args.map((arr) => new Set(arr));
503
- const setA = sets[0];
504
- for (let i = 1; i < sets.length; i++) {
505
- for (const x of sets[i].values()) {
506
- if (!setA.delete(x))
507
- setA.add(x);
508
- }
509
- }
510
- for (const x of setA.values()) {
511
- yield x;
512
- }
488
+ const sets = args.map((arr) => new Set(arr))
489
+ const setA = sets[0]
490
+ for (let i = 1; i < sets.length; i++) {
491
+ for (const x of sets[i].values()) {
492
+ if (!setA.delete(x)) setA.add(x)
493
+ }
494
+ }
495
+ for (const x of setA.values()) {
496
+ yield x
497
+ }
513
498
  }
514
499
  export function* intersection(...args) {
515
- const sets = args.map((arr) => new Set(arr));
516
- // build a counter map to find items in all
517
- const results = new Map();
518
- const total = sets.length;
519
- for (let i = 0; i < total; i++) {
520
- for (const x of sets[i].values()) {
521
- const count = results.get(x) || 0;
522
- results.set(x, count + 1);
523
- }
524
- }
525
- for (const [key, value] of results.entries()) {
526
- if (value === total)
527
- yield key;
528
- }
500
+ const sets = args.map((arr) => new Set(arr))
501
+ // build a counter map to find items in all
502
+ const results = new Map()
503
+ const total = sets.length
504
+ for (let i = 0; i < total; i++) {
505
+ for (const x of sets[i].values()) {
506
+ const count = results.get(x) || 0
507
+ results.set(x, count + 1)
508
+ }
509
+ }
510
+ for (const [key, value] of results.entries()) {
511
+ if (value === total) yield key
512
+ }
529
513
  }
530
514
  export function* union(...args) {
531
- const results = new Set();
532
- for (const arr of args) {
533
- for (const item of arr) {
534
- results.add(item);
535
- }
536
- }
537
- for (const item of results.values()) {
538
- yield item;
539
- }
515
+ const results = new Set()
516
+ for (const arr of args) {
517
+ for (const item of arr) {
518
+ results.add(item)
519
+ }
520
+ }
521
+ for (const item of results.values()) {
522
+ yield item
523
+ }
540
524
  }
541
525
  /**
542
526
  * Creates an object composed of keys generated from the results of running each element of `arr` thru `func`. The order of grouped values is determined by the order they occur in `arr`. The corresponding value of each key is an array of elements responsible for generating the key.
@@ -547,24 +531,23 @@ export function* union(...args) {
547
531
  * @return {Object} Returns the composed aggregate object.
548
532
  */
549
533
  export function groupBy(arr, func = id) {
550
- const results = {};
551
- if (Array.isArray(arr)) {
552
- for (let i = 0; i < arr.length; i++) {
553
- const item = arr[i];
554
- const groupKey = typeof func === 'function' ? func(item, i) : get(item, func);
555
- const values = results[groupKey] || [];
556
- values.push(item);
557
- results[groupKey] = values;
558
- }
559
- }
560
- else {
561
- for (const k in arr) {
562
- const item = arr[k];
563
- const groupKey = typeof func === 'function' ? func(item, k) : get(item, func);
564
- const values = results[groupKey];
565
- values.push(item);
566
- results[groupKey] = values;
567
- }
568
- }
569
- return results;
534
+ const results = {}
535
+ if (Array.isArray(arr)) {
536
+ for (let i = 0; i < arr.length; i++) {
537
+ const item = arr[i]
538
+ const groupKey = typeof func === 'function' ? func(item, i) : get(item, func)
539
+ const values = results[groupKey] || []
540
+ values.push(item)
541
+ results[groupKey] = values
542
+ }
543
+ } else {
544
+ for (const k in arr) {
545
+ const item = arr[k]
546
+ const groupKey = typeof func === 'function' ? func(item, k) : get(item, func)
547
+ const values = results[groupKey]
548
+ values.push(item)
549
+ results[groupKey] = values
550
+ }
551
+ }
552
+ return results
570
553
  }