atomic-fns 0.3.5 → 0.4.3
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 +1 -12
- package/{core → dist}/collections/BTree.d.ts +6 -6
- package/{core → dist}/collections/BTree.js +17 -17
- package/{core → dist}/collections/Heap.d.ts +3 -3
- package/{core → dist}/collections/Heap.js +0 -0
- package/dist/collections/LRUCache.d.ts +80 -0
- package/dist/collections/LRUCache.js +126 -0
- package/{core → dist}/collections/SortedMap.d.ts +2 -2
- package/{core → dist}/collections/SortedMap.js +0 -0
- package/{core → dist}/collections/SortedSet.d.ts +3 -3
- package/{core → dist}/collections/SortedSet.js +1 -1
- package/{core → dist}/collections/SortedTree.d.ts +3 -3
- package/{core → dist}/collections/SortedTree.js +1 -1
- package/{core → dist}/collections/SplayTree.d.ts +5 -5
- package/{core → dist}/collections/SplayTree.js +0 -0
- package/{core → dist}/collections/abc.d.ts +0 -0
- package/{core → dist}/collections/abc.js +0 -0
- package/{core → dist}/collections/deque.d.ts +7 -7
- package/{core → dist}/collections/deque.js +6 -8
- package/{core → dist}/collections/frozenset.d.ts +0 -0
- package/{core → dist}/collections/frozenset.js +3 -6
- package/{core → dist}/collections/index.d.ts +207 -105
- package/{core → dist}/collections/index.js +179 -436
- package/{core → dist}/functools/index.d.ts +30 -16
- package/{core → dist}/functools/index.js +34 -12
- package/dist/globals/decimal.d.ts +142 -0
- package/dist/globals/decimal.js +371 -0
- package/{core → dist}/globals/index.d.ts +26 -25
- package/{core → dist}/globals/index.js +16 -37
- package/dist/i18n/currency.d.ts +24 -0
- package/dist/i18n/currency.js +85 -0
- package/dist/i18n/date/index.d.ts +204 -0
- package/dist/i18n/date/index.js +530 -0
- package/dist/i18n/date/utils.d.ts +65 -0
- package/dist/i18n/date/utils.js +290 -0
- package/dist/i18n/duration.d.ts +112 -0
- package/dist/i18n/duration.js +392 -0
- package/dist/i18n/format.d.ts +26 -0
- package/dist/i18n/format.js +495 -0
- package/{core → dist}/i18n/index.d.ts +2 -1
- package/{core → dist}/i18n/index.js +2 -1
- package/{core → dist}/index.d.ts +0 -0
- package/{core → dist}/index.js +0 -0
- package/{core → dist}/itertools/index.d.ts +74 -46
- package/{core → dist}/itertools/index.js +28 -56
- package/{core → dist}/math/index.d.ts +9 -10
- package/{core → dist}/math/index.js +3 -1
- package/{core → dist}/operators/index.d.ts +4 -4
- package/{core → dist}/operators/index.js +2 -8
- package/{core → dist}/random/index.d.ts +1 -1
- package/{core → dist}/random/index.js +5 -5
- package/package.json +28 -42
- package/.editorconfig +0 -12
- package/.esdoc.json +0 -27
- package/.eslintignore +0 -1
- package/.eslintrc.json +0 -35
- package/.firebaserc +0 -5
- package/.prettierrc +0 -19
- package/core/collections/BTree.ts +0 -1340
- package/core/collections/Heap.ts +0 -189
- package/core/collections/LRUCache.d.ts +0 -152
- package/core/collections/LRUCache.js +0 -409
- package/core/collections/LRUCache.ts +0 -486
- package/core/collections/SortedMap.ts +0 -146
- package/core/collections/SortedSet.ts +0 -110
- package/core/collections/SortedTree.ts +0 -160
- package/core/collections/SplayTree.ts +0 -354
- package/core/collections/abc.ts +0 -176
- package/core/collections/deque.ts +0 -338
- package/core/collections/frozenset.ts +0 -37
- package/core/collections/index.ts +0 -1024
- package/core/collections/test.html +0 -10
- package/core/collections/typedArrays.d.ts +0 -31
- package/core/collections/typedArrays.js +0 -143
- package/core/collections/typedArrays.ts +0 -163
- package/core/functools/index.ts +0 -260
- package/core/globals/index.ts +0 -481
- package/core/i18n/date/format.d.ts +0 -16
- package/core/i18n/date/format.js +0 -307
- package/core/i18n/date/format.ts +0 -343
- package/core/i18n/date/index.d.ts +0 -224
- package/core/i18n/date/index.js +0 -387
- package/core/i18n/date/index.ts +0 -471
- package/core/i18n/date/test.html +0 -67
- package/core/i18n/index.ts +0 -8
- package/core/index.ts +0 -8
- package/core/itertools/index.ts +0 -494
- package/core/math/index.ts +0 -152
- package/core/operators/index.ts +0 -310
- package/core/random/index.ts +0 -66
- package/firebase.json +0 -10
- package/jasmine.json +0 -14
- package/tests/BTree.spec.ts +0 -143
- package/tests/Cache.spec.ts +0 -161
- package/tests/Heap.spec.ts +0 -66
- package/tests/SortedMap.spec.ts +0 -144
- package/tests/SortedSet.spec.ts +0 -84
- package/tests/SortedTree.spec.ts +0 -164
- package/tests/SplayTree.spec.ts +0 -121
- package/tests/collections.spec.ts +0 -288
- package/tests/deque.spec.ts +0 -107
- package/tests/globals.spec.ts +0 -270
- package/tests/itertools.spec.ts +0 -266
- package/tests/math.spec.ts +0 -25
- package/tests/operators.spec.ts +0 -40
- package/tests/random.spec.ts +0 -46
- package/tsconfig.json +0 -126
- package/tsconfig.node.json +0 -18
- package/tsconfig.xo.json +0 -9
|
@@ -3,8 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* @module Collections
|
|
5
5
|
*/
|
|
6
|
-
import {
|
|
7
|
-
import { call, get, isArray, isArrayLike, isBool, isEmpty, isFunction, isIterable, isNull, isNumber, isObject, isString, isSymbol, keys, set } from '../globals/index.js';
|
|
6
|
+
import { call, get, isArray, isArrayLike, isBool, isEmpty, isFunction, isIterable, isNull, isNumber, isObject, isString, keys, set } from '../globals/index.js';
|
|
8
7
|
import { enumerate } from '../itertools/index.js';
|
|
9
8
|
import { compare, eq, id } from '../operators/index.js';
|
|
10
9
|
export * from './abc.js';
|
|
@@ -13,12 +12,12 @@ export * from './deque.js';
|
|
|
13
12
|
export * from './frozenset.js';
|
|
14
13
|
export * from './Heap.js';
|
|
15
14
|
export * from './LRUCache.js';
|
|
16
|
-
export * from './SortedSet.js';
|
|
17
15
|
export * from './SortedMap.js';
|
|
16
|
+
export * from './SortedSet.js';
|
|
18
17
|
export * from './SortedTree.js';
|
|
19
18
|
export * from './SplayTree.js';
|
|
20
19
|
export function compact(arr) {
|
|
21
|
-
if (arr
|
|
20
|
+
if (!arr)
|
|
22
21
|
return;
|
|
23
22
|
if (Array.isArray(arr))
|
|
24
23
|
return arr.filter((x) => !isEmpty(x));
|
|
@@ -30,9 +29,9 @@ export function compact(arr) {
|
|
|
30
29
|
}
|
|
31
30
|
return result;
|
|
32
31
|
}
|
|
33
|
-
export function count(
|
|
32
|
+
export function count(obj, func) {
|
|
34
33
|
const counters = {};
|
|
35
|
-
forEach(
|
|
34
|
+
forEach(obj, (value, key) => {
|
|
36
35
|
const result = func(value, key);
|
|
37
36
|
counters[result] = get(result, counters, 0) + 1;
|
|
38
37
|
});
|
|
@@ -42,116 +41,34 @@ export function count(iterable, func) {
|
|
|
42
41
|
* Creates a function that can be used to create named tuple-like objects.
|
|
43
42
|
* @example
|
|
44
43
|
```js
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
44
|
+
let Point = namedtuple('x', 'y', 'z')
|
|
45
|
+
let userObj = User(0, 0, 0)
|
|
46
|
+
// {x: 0, y: 0, z: 0}
|
|
48
47
|
```
|
|
49
48
|
* @param fields - A list of field names
|
|
50
49
|
* @returns A function that can be called with the field values
|
|
51
50
|
*/
|
|
52
|
-
export
|
|
53
|
-
return (...args) => fields.reduce((prev, f, i) => set(f, prev, args[i], false, true), {});
|
|
54
|
-
}
|
|
55
|
-
/**
|
|
56
|
-
* Iterates over elements of collection, returning an array of all elements where predicate returns truthy value.
|
|
57
|
-
*
|
|
58
|
-
* The predicate is invoked with three arguments: `(value, index|key, arr)`.
|
|
59
|
-
*
|
|
60
|
-
* @example
|
|
61
|
-
```js
|
|
62
|
-
* let users = [
|
|
63
|
-
{ 'user': 'barney', 'age': 36, 'active': true },
|
|
64
|
-
{ 'user': 'fred', 'age': 40, 'active': false }
|
|
65
|
-
]
|
|
66
|
-
|
|
67
|
-
filter(users, o => !o.active)
|
|
68
|
-
// => objects for ['fred']
|
|
69
|
-
|
|
70
|
-
// The shape iteratee shorthand.
|
|
71
|
-
filter(users, { age: 36, active: true })
|
|
72
|
-
// => objects for ['barney']
|
|
73
|
-
|
|
74
|
-
// The property iteratee shorthand.
|
|
75
|
-
filter(users, 'active')
|
|
76
|
-
// => objects for ['barney']
|
|
77
|
-
```
|
|
78
|
-
* @param {Array} arr The collection to iterate over
|
|
79
|
-
* @param {Function} fn The predicate function invoked for each item
|
|
80
|
-
* @returns {Array} The new filtered array
|
|
81
|
-
*/
|
|
51
|
+
export const namedtuple = (...fields) => (...args) => fields.reduce((prev, f, i) => set(f, prev, args[i], false, true), {});
|
|
82
52
|
export function filter(arr, fn = isNull) {
|
|
83
|
-
if (
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
if (
|
|
89
|
-
|
|
90
|
-
}
|
|
53
|
+
if (!arr)
|
|
54
|
+
return;
|
|
55
|
+
const predicate = isFunction(fn) ? fn : isObject(fn) ? matches(fn) : (obj) => get(fn, obj);
|
|
56
|
+
const results = [];
|
|
57
|
+
forEach(arr, (value, key) => {
|
|
58
|
+
if (predicate(value, key, arr))
|
|
59
|
+
results.push(value);
|
|
60
|
+
});
|
|
61
|
+
return results;
|
|
91
62
|
}
|
|
92
|
-
/**
|
|
93
|
-
* Iterates over elements of collection, returning the first element where predicate returns truthy value. The predicate is invoked with three arguments: `(value, index|key, collection)`.
|
|
94
|
-
* @example
|
|
95
|
-
```js
|
|
96
|
-
let users = [
|
|
97
|
-
{ 'user': 'barney', 'age': 36, 'active': true },
|
|
98
|
-
{ 'user': 'fred', 'age': 40, 'active': false },
|
|
99
|
-
{ 'user': 'pebbles', 'age': 1, 'active': true }
|
|
100
|
-
]
|
|
101
|
-
|
|
102
|
-
find(users, (o) => o.age < 40)
|
|
103
|
-
// => object for 'barney'
|
|
104
|
-
|
|
105
|
-
// The shape iteratee shorthand.
|
|
106
|
-
find(users, { 'age': 1, 'active': true })
|
|
107
|
-
// => object for 'pebbles'
|
|
108
|
-
|
|
109
|
-
// The `property` iteratee shorthand.
|
|
110
|
-
find(users, 'active')
|
|
111
|
-
// => object for 'barney'
|
|
112
|
-
```
|
|
113
|
-
* @param {Array} arr The collection to iterate over.
|
|
114
|
-
* @param {Function} fn The function invoked per iteration.
|
|
115
|
-
* @returns {*} The matched element, else `undefined`.
|
|
116
|
-
* @see {@link findRight}
|
|
117
|
-
*/
|
|
118
63
|
export function find(arr, fn) {
|
|
64
|
+
const it = isFunction(fn) ? fn : isObject(fn) ? matches(fn) : (obj) => get(fn, obj);
|
|
119
65
|
if (Array.isArray(arr)) {
|
|
120
|
-
|
|
121
|
-
return arr.find(fn);
|
|
122
|
-
if (isNumber(fn) || isString(fn) || isSymbol(fn))
|
|
123
|
-
return arr.find((x) => x?.[fn]);
|
|
124
|
-
if (isObject(fn))
|
|
125
|
-
return arr.find(matches(fn));
|
|
66
|
+
return arr.find(it);
|
|
126
67
|
}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
```js
|
|
132
|
-
findRight([1, 2, 3, 4], (n) => n % 2 === 1)
|
|
133
|
-
// => 3
|
|
134
|
-
```
|
|
135
|
-
* @param {Array} arr The collection to iterate over.
|
|
136
|
-
* @param {Function} fn The function invoked per iteration.
|
|
137
|
-
* @returns {*} The matched element, else `undefined`.
|
|
138
|
-
* @see {@link find}
|
|
139
|
-
*/
|
|
140
|
-
export function findRight(arr, fn) {
|
|
141
|
-
if (Array.isArray(arr)) {
|
|
142
|
-
for (let i = arr.length - 1; i >= 0; i--) {
|
|
143
|
-
const x = arr[i];
|
|
144
|
-
if (typeof fn === 'function') {
|
|
145
|
-
if (fn(x))
|
|
146
|
-
return x;
|
|
147
|
-
}
|
|
148
|
-
else if (typeof fn === 'string') {
|
|
149
|
-
if (x?.[fn])
|
|
150
|
-
return x;
|
|
151
|
-
}
|
|
152
|
-
else if (isObject(fn)) {
|
|
153
|
-
if (matches(fn)(x))
|
|
154
|
-
return x;
|
|
68
|
+
else if (isObject(arr)) {
|
|
69
|
+
for (const key of Object.keys(arr)) {
|
|
70
|
+
if (it(arr[key], key, arr)) {
|
|
71
|
+
return arr[key];
|
|
155
72
|
}
|
|
156
73
|
}
|
|
157
74
|
}
|
|
@@ -167,7 +84,7 @@ export function findRight(arr, fn) {
|
|
|
167
84
|
* @returns {Array<*>} The given array.
|
|
168
85
|
*/
|
|
169
86
|
export function insert(arr, index, value) {
|
|
170
|
-
if (!arr ||
|
|
87
|
+
if (!arr || index < 0)
|
|
171
88
|
return arr;
|
|
172
89
|
arr.splice(index, 0, value);
|
|
173
90
|
return arr;
|
|
@@ -182,7 +99,7 @@ let objects = [
|
|
|
182
99
|
]
|
|
183
100
|
|
|
184
101
|
filter(objects, matches({ a: 4, c: 6 }))
|
|
185
|
-
//
|
|
102
|
+
// [{ a: 4, b: 5, c: 6 }]
|
|
186
103
|
```
|
|
187
104
|
* @param shape
|
|
188
105
|
* @returns
|
|
@@ -201,48 +118,42 @@ export function forEach(collection, fn) {
|
|
|
201
118
|
for (let i = 0; i < collection.length; i++) {
|
|
202
119
|
const res = fn(collection[i], i, collection);
|
|
203
120
|
if (res === false)
|
|
204
|
-
return
|
|
121
|
+
return;
|
|
205
122
|
}
|
|
206
123
|
}
|
|
207
124
|
else if (isIterable(collection)) {
|
|
208
125
|
for (const [index, value] of enumerate(collection)) {
|
|
209
126
|
const res = fn(value, index, collection);
|
|
210
127
|
if (res === false)
|
|
211
|
-
return
|
|
128
|
+
return;
|
|
212
129
|
}
|
|
213
130
|
}
|
|
214
131
|
else {
|
|
215
132
|
for (const key of keys(collection)) {
|
|
216
133
|
const res = fn(collection[key], key, collection);
|
|
217
134
|
if (res === false)
|
|
218
|
-
return
|
|
135
|
+
return;
|
|
219
136
|
}
|
|
220
137
|
}
|
|
221
138
|
}
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
* @param {Iteratee} fn The function invoked per iteration.
|
|
234
|
-
* @returns {*} Returns `collection`.
|
|
235
|
-
* @see {@link forEach}
|
|
236
|
-
* @see {@link filter}
|
|
237
|
-
* @see {@link map}
|
|
238
|
-
*/
|
|
139
|
+
export function findLast(arr, fn) {
|
|
140
|
+
let result;
|
|
141
|
+
const it = isFunction(fn) ? fn : matches(fn);
|
|
142
|
+
forEachRight(arr, (val, key) => {
|
|
143
|
+
if (it(val, key, arr)) {
|
|
144
|
+
result = val;
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
return result;
|
|
149
|
+
}
|
|
239
150
|
export function forEachRight(collection, fn) {
|
|
240
151
|
if (Array.isArray(collection)) {
|
|
241
152
|
for (let i = collection.length - 1; i >= 0; i--) {
|
|
242
153
|
const value = collection[i];
|
|
243
154
|
const res = fn(value, i, collection);
|
|
244
155
|
if (res === false)
|
|
245
|
-
return
|
|
156
|
+
return;
|
|
246
157
|
}
|
|
247
158
|
}
|
|
248
159
|
else if (isObject(collection)) {
|
|
@@ -250,50 +161,12 @@ export function forEachRight(collection, fn) {
|
|
|
250
161
|
for (let i = keys.length - 1; i >= 0; i--) {
|
|
251
162
|
const key = keys[i];
|
|
252
163
|
const value = collection[key];
|
|
253
|
-
const res = fn(value,
|
|
164
|
+
const res = fn(value, key, collection);
|
|
254
165
|
if (res === false)
|
|
255
|
-
return
|
|
166
|
+
return;
|
|
256
167
|
}
|
|
257
168
|
}
|
|
258
|
-
return collection;
|
|
259
|
-
}
|
|
260
|
-
/**
|
|
261
|
-
* Flattens an array or object. Arrays will be flattened recursively up to `depth` times. Objects will be flattened recursively.
|
|
262
|
-
* @example
|
|
263
|
-
```js
|
|
264
|
-
flatten([1, [2, [3, [4]], 5]])
|
|
265
|
-
// => [1, 2, [3, [4]], 5]
|
|
266
|
-
|
|
267
|
-
flatten({
|
|
268
|
-
dates: {
|
|
269
|
-
expiry_date: '30 sep 2018',
|
|
270
|
-
available: '30 sep 2017',
|
|
271
|
-
min_contract_period: [
|
|
272
|
-
{
|
|
273
|
-
id: 1,
|
|
274
|
-
name: '1 month'
|
|
275
|
-
}
|
|
276
|
-
]
|
|
277
|
-
},
|
|
278
|
-
price: {
|
|
279
|
-
currency: 'RM',
|
|
280
|
-
value: 1500
|
|
281
|
-
}
|
|
282
|
-
})
|
|
283
|
-
// => {
|
|
284
|
-
'dates.expiry_date': '30 sep 2018',
|
|
285
|
-
'dates.available': '30 sep 2017',
|
|
286
|
-
'dates.min_contract_period[0].id': 1,
|
|
287
|
-
'dates.min_contract_period[0].name': '1 month',
|
|
288
|
-
'price.currency': 'RM',
|
|
289
|
-
'price.value': 1500
|
|
290
169
|
}
|
|
291
|
-
```
|
|
292
|
-
* @param {Array|Object} arr The array or object to flatten.
|
|
293
|
-
* @param {number} [depth=1] The max recursion depth.
|
|
294
|
-
* @returns {*} The new flattened array or object.
|
|
295
|
-
* @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flat Array.flat()}
|
|
296
|
-
*/
|
|
297
170
|
export function flatten(arr, depth = 1) {
|
|
298
171
|
if (!depth)
|
|
299
172
|
return arr;
|
|
@@ -339,73 +212,20 @@ function flattenObj(obj, prefix = '', result = {}, keepNull = false) {
|
|
|
339
212
|
}
|
|
340
213
|
return result;
|
|
341
214
|
}
|
|
342
|
-
/**
|
|
343
|
-
* Creates an array of values by running each element in collection thru iteratee. The iteratee is invoked with three arguments: `(value, index|key, collection)`.
|
|
344
|
-
* @example
|
|
345
|
-
```js
|
|
346
|
-
function square(n) {
|
|
347
|
-
return n * n
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
map([4, 8], square)
|
|
351
|
-
// => [16, 64]
|
|
352
|
-
|
|
353
|
-
map({ a: 4, b: 8 }, square)
|
|
354
|
-
// => [16, 64] (iteration order is not guaranteed)
|
|
355
|
-
|
|
356
|
-
let users = [
|
|
357
|
-
{ user: 'barney' },
|
|
358
|
-
{ user: 'fred' }
|
|
359
|
-
]
|
|
360
|
-
|
|
361
|
-
// The `property` iteratee shorthand.
|
|
362
|
-
map(users, 'user')
|
|
363
|
-
// => ['barney', 'fred']
|
|
364
|
-
```
|
|
365
|
-
* @param {Array|Object} arr The collection to iterate over.
|
|
366
|
-
* @param {Iteratee|PropertyKey} fn The function invoked per iteration.
|
|
367
|
-
* @returns Returns the new mapped array.
|
|
368
|
-
* @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map Array.map()}
|
|
369
|
-
*/
|
|
370
215
|
export function map(arr, fn) {
|
|
216
|
+
const it = isFunction(fn) ? fn : (obj) => get(fn, obj);
|
|
371
217
|
if (Array.isArray(arr)) {
|
|
372
|
-
return arr.map((x, i) =>
|
|
373
|
-
if (typeof fn === 'function')
|
|
374
|
-
return fn(x, i, arr);
|
|
375
|
-
return x?.[fn];
|
|
376
|
-
});
|
|
218
|
+
return arr.map((x, i) => it(x, i, arr));
|
|
377
219
|
}
|
|
378
220
|
if (isObject(arr)) {
|
|
379
|
-
return Object.keys(arr).map((key) =>
|
|
380
|
-
if (typeof fn === 'function')
|
|
381
|
-
return fn(arr[key], key, arr);
|
|
382
|
-
return get(fn, arr[key]);
|
|
383
|
-
});
|
|
221
|
+
return Object.keys(arr).map((key) => it(arr[key], key, arr));
|
|
384
222
|
}
|
|
385
223
|
}
|
|
386
|
-
/**
|
|
387
|
-
* Creates an object composed of the picked object properties.
|
|
388
|
-
* @param {Object} obj The source object.
|
|
389
|
-
* @param {Iteratee|PropertyKey[]} paths The properties to pick. If `paths` is a function, it will be invoked per property with two values `(value, key)`.
|
|
390
|
-
* @returns A new object with the properties.
|
|
391
|
-
* @example
|
|
392
|
-
```js
|
|
393
|
-
let object = { a: 1, b: '2', c: 3 }
|
|
394
|
-
|
|
395
|
-
pick(object, ['a', 'c'])
|
|
396
|
-
// => { a: 1, c: 3 }
|
|
397
|
-
|
|
398
|
-
pick(object, (x) => isNumber(x))
|
|
399
|
-
// => { a: 1, c: 3 }
|
|
400
|
-
```
|
|
401
|
-
*
|
|
402
|
-
* @see {@link omit}
|
|
403
|
-
*/
|
|
404
224
|
export function pick(obj, paths) {
|
|
405
225
|
if (!obj)
|
|
406
226
|
return {};
|
|
407
227
|
const result = {};
|
|
408
|
-
if (
|
|
228
|
+
if (isFunction(paths)) {
|
|
409
229
|
for (const key of Object.keys(obj)) {
|
|
410
230
|
if (paths(obj[key], key)) {
|
|
411
231
|
result[key] = obj[key];
|
|
@@ -418,28 +238,11 @@ export function pick(obj, paths) {
|
|
|
418
238
|
}
|
|
419
239
|
return result;
|
|
420
240
|
}
|
|
421
|
-
/**
|
|
422
|
-
* The opposite of {@link pick} - this method creates an object composed of the own and inherited enumerable property paths of `object` that are not omitted.
|
|
423
|
-
* @example
|
|
424
|
-
```js
|
|
425
|
-
let object = { 'a': 1, 'b': '2', 'c': 3 }
|
|
426
|
-
|
|
427
|
-
omit(object, ['a', 'c'])
|
|
428
|
-
// => { 'b': '2' }
|
|
429
|
-
|
|
430
|
-
omit(object, (x) => isNumber(x))
|
|
431
|
-
// => { 'b': '2' }
|
|
432
|
-
```
|
|
433
|
-
* @param {Object} obj The source object.
|
|
434
|
-
* @param {Iteratee|PropertyKey[]} paths The property paths to omit.
|
|
435
|
-
* @returns {Object} Returns the new object.
|
|
436
|
-
* @see {@link pick}
|
|
437
|
-
*/
|
|
438
241
|
export function omit(obj, paths) {
|
|
439
242
|
if (!obj)
|
|
440
243
|
return {};
|
|
441
244
|
const result = {};
|
|
442
|
-
if (
|
|
245
|
+
if (isFunction(paths)) {
|
|
443
246
|
for (const key of Object.keys(obj)) {
|
|
444
247
|
if (!paths(obj[key], key)) {
|
|
445
248
|
result[key] = obj[key];
|
|
@@ -453,61 +256,24 @@ export function omit(obj, paths) {
|
|
|
453
256
|
}
|
|
454
257
|
return result;
|
|
455
258
|
}
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
* @param {string|Object|Iteratee} fn The predicate function
|
|
460
|
-
* @param {number} [start=0] The index to search from.
|
|
461
|
-
* @returns {number} The index of the found value, else -1
|
|
462
|
-
* @example
|
|
463
|
-
```js
|
|
464
|
-
let users = [
|
|
465
|
-
{ 'user': 'barney', 'active': false },
|
|
466
|
-
{ 'user': 'fred', 'active': false },
|
|
467
|
-
{ 'user': 'pebbles', 'active': true }
|
|
468
|
-
]
|
|
469
|
-
|
|
470
|
-
index(users, (o) => o.user == 'barney')
|
|
471
|
-
// => 0
|
|
472
|
-
|
|
473
|
-
// The `shape` iteratee shorthand.
|
|
474
|
-
index(users, { 'user': 'fred', 'active': false })
|
|
475
|
-
// => 1
|
|
476
|
-
|
|
477
|
-
// The `property` iteratee shorthand.
|
|
478
|
-
index(users, 'active')
|
|
479
|
-
// => 2
|
|
480
|
-
```
|
|
481
|
-
* @see {@link indexOf}
|
|
482
|
-
* @see {@link lastIndex}
|
|
483
|
-
*
|
|
484
|
-
*/
|
|
485
|
-
export function index(obj, fn, start = 0) {
|
|
486
|
-
if (obj == null)
|
|
487
|
-
return;
|
|
259
|
+
export function findIndex(obj, fn, start = 0) {
|
|
260
|
+
if (!obj)
|
|
261
|
+
return -1;
|
|
488
262
|
const length = obj.length;
|
|
489
263
|
if (length && start < 0) {
|
|
490
264
|
start = Math.max(start + length, 0);
|
|
491
265
|
}
|
|
492
266
|
if (!length || start >= length)
|
|
493
267
|
return -1;
|
|
494
|
-
|
|
495
|
-
fn = matches(fn);
|
|
496
|
-
}
|
|
268
|
+
const it = isFunction(fn) ? fn : isObject(fn) ? matches(fn) : (obj) => get(fn, obj);
|
|
497
269
|
for (; start < length; start++) {
|
|
498
|
-
if (
|
|
499
|
-
|
|
500
|
-
return start;
|
|
501
|
-
}
|
|
502
|
-
else {
|
|
503
|
-
if (obj[start]?.[fn])
|
|
504
|
-
return start;
|
|
505
|
-
}
|
|
270
|
+
if (it(obj[start], start, obj))
|
|
271
|
+
return start;
|
|
506
272
|
}
|
|
507
273
|
return -1;
|
|
508
274
|
}
|
|
509
275
|
/**
|
|
510
|
-
* This method is like {@link
|
|
276
|
+
* This method is like {@link findIndex} except that it searches for a given value directly, instead of using a predicate function.
|
|
511
277
|
* @param {Array} obj The array to inspect.
|
|
512
278
|
* @param {*} value The value to find
|
|
513
279
|
* @param {number} [start=0] The index to search from.
|
|
@@ -515,18 +281,18 @@ export function index(obj, fn, start = 0) {
|
|
|
515
281
|
* @example
|
|
516
282
|
```js
|
|
517
283
|
indexOf([1, 2, 1, 2], 2)
|
|
518
|
-
//
|
|
284
|
+
// 1
|
|
519
285
|
|
|
520
286
|
// Search from a `start` index.
|
|
521
287
|
indexOf([1, 2, 1, 2], 2, 2)
|
|
522
|
-
//
|
|
288
|
+
// 3
|
|
523
289
|
```
|
|
524
|
-
* @see {@link
|
|
290
|
+
* @see {@link findIndex}
|
|
525
291
|
* @see {@link lastIndexOf}
|
|
526
292
|
*/
|
|
527
293
|
export function indexOf(obj, value, start = 0) {
|
|
528
|
-
if (obj
|
|
529
|
-
return;
|
|
294
|
+
if (!obj)
|
|
295
|
+
return -1;
|
|
530
296
|
const op = call(obj, 'indexOf', value, start);
|
|
531
297
|
if (op != null)
|
|
532
298
|
return op;
|
|
@@ -542,54 +308,18 @@ export function indexOf(obj, value, start = 0) {
|
|
|
542
308
|
}
|
|
543
309
|
return -1;
|
|
544
310
|
}
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
* @param {number} [start] The index to search from.
|
|
550
|
-
* @returns {number} The index of the found value, else -1
|
|
551
|
-
* @example
|
|
552
|
-
```js
|
|
553
|
-
let users = [
|
|
554
|
-
{ 'user': 'barney', 'active': true },
|
|
555
|
-
{ 'user': 'fred', 'active': false },
|
|
556
|
-
{ 'user': 'pebbles', 'active': false }
|
|
557
|
-
]
|
|
558
|
-
|
|
559
|
-
findLastIndex(users, (o) => o.user == 'pebbles')
|
|
560
|
-
// => 2
|
|
561
|
-
|
|
562
|
-
// The `shape` iteratee shorthand.
|
|
563
|
-
findLastIndex(users, { 'user': 'barney', 'active': true })
|
|
564
|
-
// => 0
|
|
565
|
-
|
|
566
|
-
// The `property` iteratee shorthand.
|
|
567
|
-
findLastIndex(users, 'active')
|
|
568
|
-
// => 0
|
|
569
|
-
```
|
|
570
|
-
* @see {@link index}
|
|
571
|
-
* @see {@link lastIndexOf}
|
|
572
|
-
*/
|
|
573
|
-
export function lastIndex(obj, fn, start) {
|
|
574
|
-
if (obj == null)
|
|
575
|
-
return;
|
|
576
|
-
const length = obj.length;
|
|
311
|
+
export function findLastIndex(arr, fn, start) {
|
|
312
|
+
if (arr == null)
|
|
313
|
+
return -1;
|
|
314
|
+
const length = arr.length;
|
|
577
315
|
if (start == null)
|
|
578
316
|
start = length - 1;
|
|
579
317
|
if (!length || start < 0)
|
|
580
318
|
return -1;
|
|
581
|
-
|
|
582
|
-
fn = matches(fn);
|
|
583
|
-
}
|
|
319
|
+
const it = isFunction(fn) ? fn : isObject(fn) ? matches(fn) : (obj) => get(fn, obj);
|
|
584
320
|
for (; start >= 0; start--) {
|
|
585
|
-
if (
|
|
586
|
-
|
|
587
|
-
return start;
|
|
588
|
-
}
|
|
589
|
-
else {
|
|
590
|
-
if (obj[start]?.[fn])
|
|
591
|
-
return start;
|
|
592
|
-
}
|
|
321
|
+
if (it(arr[start], start, arr))
|
|
322
|
+
return start;
|
|
593
323
|
}
|
|
594
324
|
return -1;
|
|
595
325
|
}
|
|
@@ -602,18 +332,18 @@ export function lastIndex(obj, fn, start) {
|
|
|
602
332
|
* @example
|
|
603
333
|
```js
|
|
604
334
|
lastIndexOf([1, 2, 1, 2], 2)
|
|
605
|
-
//
|
|
335
|
+
// 3
|
|
606
336
|
|
|
607
337
|
// Search from the `fromIndex`.
|
|
608
338
|
lastIndexOf([1, 2, 1, 2], 2, 2)
|
|
609
|
-
//
|
|
339
|
+
// 1
|
|
610
340
|
```
|
|
611
|
-
* @see {@link
|
|
341
|
+
* @see {@link findLastIndex}
|
|
612
342
|
* @see {@link indexOf}
|
|
613
343
|
*/
|
|
614
344
|
export function lastIndexOf(obj, value, start) {
|
|
615
345
|
if (obj == null)
|
|
616
|
-
return;
|
|
346
|
+
return -1;
|
|
617
347
|
const op = call(obj, 'lastIndexOf', value, start);
|
|
618
348
|
if (op != null)
|
|
619
349
|
return op;
|
|
@@ -628,14 +358,6 @@ export function lastIndexOf(obj, value, start) {
|
|
|
628
358
|
}
|
|
629
359
|
return -1;
|
|
630
360
|
}
|
|
631
|
-
/**
|
|
632
|
-
* Creates a shallow clone of `value`. If `deep` is `true` it will clone it recursively.
|
|
633
|
-
* @param {*} value
|
|
634
|
-
* @param {boolean} [deep=false]
|
|
635
|
-
* @return The clone value
|
|
636
|
-
* @see {@link cloneArray}
|
|
637
|
-
* @see {@link cloneTypedArray}
|
|
638
|
-
*/
|
|
639
361
|
export function clone(value, deep = false) {
|
|
640
362
|
if (ArrayBuffer.isView(value) || value instanceof ArrayBuffer) {
|
|
641
363
|
return cloneTypedArray(value, deep);
|
|
@@ -679,46 +401,18 @@ export function cloneArray(arr, deep = false) {
|
|
|
679
401
|
* @returns The new array
|
|
680
402
|
* @see {@link clone}
|
|
681
403
|
*/
|
|
682
|
-
export function cloneTypedArray(typedArray, isDeep) {
|
|
404
|
+
export function cloneTypedArray(typedArray, isDeep = false) {
|
|
683
405
|
const buffer = isDeep ? structuredClone(typedArray) : typedArray.buffer;
|
|
684
406
|
return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length);
|
|
685
407
|
}
|
|
686
|
-
/**
|
|
687
|
-
* Creates a duplicate-free version of an array, using a `Set` for equality comparisons, in which only the first occurrence of each element is kept. The order of result values is not guaranteed.
|
|
688
|
-
* @param arr The array containing duplicated elements
|
|
689
|
-
* @param fn The iteratee invoked per element.
|
|
690
|
-
* @returns Returns the new duplicate free array.
|
|
691
|
-
* @example
|
|
692
|
-
```js
|
|
693
|
-
uniq([2, 1, 2])
|
|
694
|
-
// => [2, 1]
|
|
695
|
-
|
|
696
|
-
uniq([2.1, 1.2, 2.3], Math.floor)
|
|
697
|
-
// => [2.1, 1.2]
|
|
698
|
-
```
|
|
699
|
-
*
|
|
700
|
-
* @see {@link sortedUniq}
|
|
701
|
-
*/
|
|
702
408
|
export function uniq(arr, fn = id) {
|
|
703
409
|
const keys = new Set();
|
|
704
|
-
const
|
|
410
|
+
const it = isFunction(fn) ? fn : (x) => get(fn, x);
|
|
705
411
|
for (const x of arr) {
|
|
706
|
-
keys.add(
|
|
412
|
+
keys.add(it(x));
|
|
707
413
|
}
|
|
708
414
|
return Array.from(keys.values());
|
|
709
415
|
}
|
|
710
|
-
/**
|
|
711
|
-
* This method is like {@link uniq} except that it sorts the results in ascending order
|
|
712
|
-
* @param arr The array containing duplicated elements
|
|
713
|
-
* @param fn The iteratee invoked per element.
|
|
714
|
-
* @returns Returns the new duplicate free array
|
|
715
|
-
* @example
|
|
716
|
-
```js
|
|
717
|
-
uniq([2, 1, 2])
|
|
718
|
-
// => [1, 2]
|
|
719
|
-
```
|
|
720
|
-
* @see {@link uniq}
|
|
721
|
-
*/
|
|
722
416
|
export function sortedUniq(arr, fn = id) {
|
|
723
417
|
const values = uniq(arr, fn);
|
|
724
418
|
values.sort(compare);
|
|
@@ -804,7 +498,7 @@ let other = {
|
|
|
804
498
|
}
|
|
805
499
|
|
|
806
500
|
merge(object, other)
|
|
807
|
-
//
|
|
501
|
+
// { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] }
|
|
808
502
|
```
|
|
809
503
|
*/
|
|
810
504
|
export function merge(object, ...sources) {
|
|
@@ -823,7 +517,7 @@ export function merge(object, ...sources) {
|
|
|
823
517
|
* @example
|
|
824
518
|
```js
|
|
825
519
|
defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 })
|
|
826
|
-
//
|
|
520
|
+
// { 'a': 1, 'b': 2 }
|
|
827
521
|
```
|
|
828
522
|
*/
|
|
829
523
|
export function defaults(object, ...sources) {
|
|
@@ -842,7 +536,7 @@ export function defaults(object, ...sources) {
|
|
|
842
536
|
* @example
|
|
843
537
|
```js
|
|
844
538
|
[...difference([2, 1], [2, 3])]
|
|
845
|
-
//
|
|
539
|
+
// [1]
|
|
846
540
|
```
|
|
847
541
|
* @see {@link union}
|
|
848
542
|
* @see {@link intersection}
|
|
@@ -866,7 +560,7 @@ export function* difference(...args) {
|
|
|
866
560
|
* @example
|
|
867
561
|
```js
|
|
868
562
|
[...intersection([2, 1], [2, 3])]
|
|
869
|
-
//
|
|
563
|
+
// [2]
|
|
870
564
|
```
|
|
871
565
|
* @see {@link difference}
|
|
872
566
|
* @see {@link union}
|
|
@@ -893,7 +587,7 @@ export function* intersection(...args) {
|
|
|
893
587
|
* @example
|
|
894
588
|
```js
|
|
895
589
|
[...union([2], [1, 2])]
|
|
896
|
-
//
|
|
590
|
+
// [2, 1]
|
|
897
591
|
```
|
|
898
592
|
* @see {@link difference}
|
|
899
593
|
* @see {@link intersection}
|
|
@@ -909,26 +603,9 @@ export function* union(...args) {
|
|
|
909
603
|
yield item;
|
|
910
604
|
}
|
|
911
605
|
}
|
|
912
|
-
/**
|
|
913
|
-
* 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.
|
|
914
|
-
*
|
|
915
|
-
* @param arr The collection to iterate over.
|
|
916
|
-
* @param [func=id] The iteratee to transform keys.
|
|
917
|
-
* @returns Returns the aggregated object.
|
|
918
|
-
*
|
|
919
|
-
* @example
|
|
920
|
-
```js
|
|
921
|
-
groupBy([6.1, 4.2, 6.3], Math.floor)
|
|
922
|
-
// => { '4': [4.2], '6': [6.1, 6.3] }
|
|
923
|
-
|
|
924
|
-
// The `property` iteratee shorthand.
|
|
925
|
-
groupBy(['one', 'two', 'three'], 'length')
|
|
926
|
-
// => { '3': ['one', 'two'], '5': ['three'] }
|
|
927
|
-
```
|
|
928
|
-
*/
|
|
929
606
|
export function groupBy(arr, func = id) {
|
|
607
|
+
const useKey = isFunction(func) ? func : (obj) => get(func, obj);
|
|
930
608
|
const results = {};
|
|
931
|
-
const useKey = typeof func === 'function' ? func : partial(get, func);
|
|
932
609
|
forEach(arr, (value) => {
|
|
933
610
|
const groupKey = useKey(value);
|
|
934
611
|
const values = results[groupKey] || [];
|
|
@@ -937,27 +614,9 @@ export function groupBy(arr, func = id) {
|
|
|
937
614
|
});
|
|
938
615
|
return results;
|
|
939
616
|
}
|
|
940
|
-
/**
|
|
941
|
-
* Similar to {@link groupBy} but it returns a {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map Map} object with the results.
|
|
942
|
-
*
|
|
943
|
-
* @param arr The collection to iterate over.
|
|
944
|
-
* @param {Function | PropertyKey} [func=id] The iteratee to transform keys.
|
|
945
|
-
* @returns {Map} Returns the aggregated map object.
|
|
946
|
-
* @template K, V
|
|
947
|
-
*
|
|
948
|
-
* @example
|
|
949
|
-
```js
|
|
950
|
-
groupByMap([6.1, 4.2, 6.3], Math.floor)
|
|
951
|
-
// => Map { 4: [4.2], 6: [6.1, 6.3] }
|
|
952
|
-
|
|
953
|
-
// The `property` iteratee shorthand.
|
|
954
|
-
groupByMap(['one', 'two', 'three'], 'length')
|
|
955
|
-
// => Map { 3: ['one', 'two'], 5: ['three'] }
|
|
956
|
-
```
|
|
957
|
-
*/
|
|
958
617
|
export function groupByMap(arr, func = id) {
|
|
959
618
|
const results = new Map();
|
|
960
|
-
const useKey =
|
|
619
|
+
const useKey = isFunction(func) ? func : (obj) => get(func, obj);
|
|
961
620
|
forEach(arr, (value) => {
|
|
962
621
|
const groupKey = useKey(value);
|
|
963
622
|
const values = results.get(groupKey) || [];
|
|
@@ -966,20 +625,104 @@ export function groupByMap(arr, func = id) {
|
|
|
966
625
|
});
|
|
967
626
|
return results;
|
|
968
627
|
}
|
|
628
|
+
export function remove(arr, func) {
|
|
629
|
+
const it = isFunction(func) ? func : isArray(func) ? (x) => func.includes(x) : (x) => func === x;
|
|
630
|
+
return arr.filter((x, i) => !it(x, i, arr));
|
|
631
|
+
}
|
|
969
632
|
/**
|
|
970
|
-
*
|
|
971
|
-
*
|
|
972
|
-
* @param
|
|
973
|
-
* @
|
|
633
|
+
* Returns the index of `x` in a **sorted** array if found, in `O(log n)` using binary search.
|
|
634
|
+
* If the element is not found, returns a negative integer.
|
|
635
|
+
* @param arr The array to sort
|
|
636
|
+
* @param x The element to find
|
|
637
|
+
* @param lo The starting index
|
|
638
|
+
* @param hi The end index to search within
|
|
639
|
+
* @param comp The compare function to check for `x`
|
|
640
|
+
* @returns {number} The index if the element is found or a negative integer.
|
|
974
641
|
*/
|
|
975
|
-
export function
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
642
|
+
export function binarySearch(arr, x, lo = 0, hi, comp = compare) {
|
|
643
|
+
hi = hi ?? arr.length - 1;
|
|
644
|
+
while (lo < hi) {
|
|
645
|
+
const mid = (lo + hi) >> 1;
|
|
646
|
+
const check = comp(x, arr[mid]);
|
|
647
|
+
if (check === 0)
|
|
648
|
+
return mid;
|
|
649
|
+
if (check > 0)
|
|
650
|
+
lo = mid + 1;
|
|
651
|
+
else
|
|
652
|
+
hi = mid - 1;
|
|
653
|
+
}
|
|
654
|
+
if (comp(x, arr[lo]) === 0)
|
|
655
|
+
return lo;
|
|
656
|
+
// Returns (-lo - 1) where n is the insertion point for new element in the range
|
|
657
|
+
return -lo - 1;
|
|
658
|
+
}
|
|
659
|
+
/**
|
|
660
|
+
* Returns an insertion index which comes after any existing entries of `x` in a **sorted** array, using binary search.
|
|
661
|
+
* @param arr The array to sort
|
|
662
|
+
* @param x The element to find
|
|
663
|
+
* @param lo The starting index
|
|
664
|
+
* @param hi The end index to search within
|
|
665
|
+
* @param comp The compare function to check for `x`
|
|
666
|
+
* @returns {number}
|
|
667
|
+
*/
|
|
668
|
+
export function bisect(arr, x, lo = 0, hi, comp = compare) {
|
|
669
|
+
hi = hi ?? arr.length;
|
|
670
|
+
while (lo < hi) {
|
|
671
|
+
const mid = (lo + hi) >> 1;
|
|
672
|
+
const check = comp(x, arr[mid]);
|
|
673
|
+
if (check >= 0)
|
|
674
|
+
lo = mid + 1;
|
|
675
|
+
else
|
|
676
|
+
hi = mid - 1;
|
|
677
|
+
}
|
|
678
|
+
return lo;
|
|
679
|
+
}
|
|
680
|
+
/**
|
|
681
|
+
* Returns an insertion index which comes before any existing entries of `x` in a **sorted** array, using binary search.
|
|
682
|
+
* @param arr The array to sort
|
|
683
|
+
* @param x The element to find
|
|
684
|
+
* @param lo The starting index
|
|
685
|
+
* @param hi The end index to search within
|
|
686
|
+
* @param comp The compare function to check for `x`
|
|
687
|
+
* @returns {number}
|
|
688
|
+
*/
|
|
689
|
+
export function bisectLeft(arr, x, lo = 0, hi, comp = compare) {
|
|
690
|
+
hi = hi ?? arr.length;
|
|
691
|
+
while (lo < hi) {
|
|
692
|
+
const mid = (lo + hi) >> 1;
|
|
693
|
+
const check = comp(x, arr[mid]);
|
|
694
|
+
if (check <= 0)
|
|
695
|
+
hi = mid - 1;
|
|
696
|
+
else
|
|
697
|
+
lo = mid + 1;
|
|
698
|
+
}
|
|
699
|
+
return lo;
|
|
700
|
+
}
|
|
701
|
+
/**
|
|
702
|
+
* Runs {@link bisect} first to locate an insertion point, and inserts the value `x` in the sorted array after any existing entries of `x` to maintain sort order.
|
|
703
|
+
* Please note this method is `O(n)` because insertion resizes the array.
|
|
704
|
+
* @param arr The array to insert into
|
|
705
|
+
* @param x The element to insert
|
|
706
|
+
* @param lo The starting index
|
|
707
|
+
* @param hi The end index to search within
|
|
708
|
+
* @param comp The compare function to check for `x`
|
|
709
|
+
* @returns {Array}
|
|
710
|
+
*/
|
|
711
|
+
export function insort(arr, x, lo = 0, hi, comp = compare) {
|
|
712
|
+
const index = bisect(arr, x, lo, hi, comp);
|
|
713
|
+
return insert(arr, index, x);
|
|
714
|
+
}
|
|
715
|
+
/**
|
|
716
|
+
* Runs {@link bisectLeft} first to locate an insertion point, and inserts the value `x` in the sorted array before any existing entries of `x` to maintain sort order.
|
|
717
|
+
* Please note this method is `O(n)` because insertion resizes the array.
|
|
718
|
+
* @param arr The array to insert into
|
|
719
|
+
* @param x The element to insert
|
|
720
|
+
* @param lo The starting index
|
|
721
|
+
* @param hi The end index to search within
|
|
722
|
+
* @param comp The compare function to check for `x`
|
|
723
|
+
* @returns {Array}
|
|
724
|
+
*/
|
|
725
|
+
export function insortLeft(arr, x, lo = 0, hi, comp = compare) {
|
|
726
|
+
const index = bisectLeft(arr, x, lo, hi, comp);
|
|
727
|
+
return insert(arr, index, x);
|
|
983
728
|
}
|
|
984
|
-
// TODO: binary search utils
|
|
985
|
-
// TODO: Counter
|