@tim-code/my-util 0.5.0 → 0.5.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.
- package/package.json +1 -1
- package/src/find.js +41 -11
- package/src/find.test.js +55 -16
- package/src/math.js +1 -1
- package/src/math.test.js +3 -3
package/package.json
CHANGED
package/src/find.js
CHANGED
|
@@ -1,4 +1,30 @@
|
|
|
1
|
-
export function
|
|
1
|
+
export function findEq(array, desired, { key } = {}) {
|
|
2
|
+
if (typeof key === "function") {
|
|
3
|
+
for (let i = 0; i < array.length; i++) {
|
|
4
|
+
const element = array[i]
|
|
5
|
+
const value = key(element, i, array)
|
|
6
|
+
if (value === desired) {
|
|
7
|
+
return value
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
} else if (typeof key === "number" || typeof key === "string") {
|
|
11
|
+
for (const element of array) {
|
|
12
|
+
const value = element[key]
|
|
13
|
+
if (value === desired) {
|
|
14
|
+
return value
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
} else {
|
|
18
|
+
for (const value of array) {
|
|
19
|
+
if (value === desired) {
|
|
20
|
+
return value
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return undefined
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function findSmallestDiff(array, desired, { key, cutoff = Infinity } = {}) {
|
|
2
28
|
let closest
|
|
3
29
|
if (typeof key === "function") {
|
|
4
30
|
for (let i = 0; i < array.length; i++) {
|
|
@@ -163,14 +189,16 @@ export function findClosestGTE(array, desired, { key, cutoff = Infinity } = {})
|
|
|
163
189
|
* @param {string|number|Function=} options.key
|
|
164
190
|
* If specified, will consider the value for each element's key instead of the element itself.
|
|
165
191
|
* If a function, called with the element, index and array (same as .map() callback) to produce the value to sort on.
|
|
166
|
-
* @param {string=} options.comparator "
|
|
192
|
+
* @param {string=} options.comparator "diff", "lt", "lte", "gt", "gte", "eq". Default is "diff" which implies T is number.
|
|
167
193
|
* @param {V=} options.cutoff If specified, sets a initial constraint on how close the found value must be.
|
|
168
|
-
*
|
|
169
|
-
* If used with
|
|
194
|
+
* If used with lt, lte, value must be greater than or equal to cutoff.
|
|
195
|
+
* If used with gt, gte, value must be less than or equal to cutoff.
|
|
196
|
+
* If used with diff, value's difference with desired must be less than or equal to cutoff.
|
|
197
|
+
* No effect with eq.
|
|
170
198
|
* @returns {T|undefined}
|
|
171
199
|
*/
|
|
172
200
|
export function findClosest(array, value, options = {}) {
|
|
173
|
-
const { comparator = "
|
|
201
|
+
const { comparator = "diff" } = options
|
|
174
202
|
switch (comparator) {
|
|
175
203
|
case "lt":
|
|
176
204
|
return findClosestLT(array, value, options)
|
|
@@ -180,15 +208,17 @@ export function findClosest(array, value, options = {}) {
|
|
|
180
208
|
return findClosestGT(array, value, options)
|
|
181
209
|
case "gte":
|
|
182
210
|
return findClosestGTE(array, value, options)
|
|
183
|
-
case "
|
|
184
|
-
return
|
|
211
|
+
case "diff":
|
|
212
|
+
return findSmallestDiff(array, value, options)
|
|
213
|
+
case "eq":
|
|
214
|
+
return findEq(array, value, options)
|
|
185
215
|
default:
|
|
186
216
|
throw new Error(`unknown comparator: ${comparator}`)
|
|
187
217
|
}
|
|
188
218
|
}
|
|
189
219
|
|
|
190
220
|
/**
|
|
191
|
-
* Find the minimum value in an array.
|
|
221
|
+
* Find the minimum value in an array. undefined or null values are ignored.
|
|
192
222
|
* @template T, V
|
|
193
223
|
* @param {Array<T>} array
|
|
194
224
|
* @param {Object} $1
|
|
@@ -196,7 +226,7 @@ export function findClosest(array, value, options = {}) {
|
|
|
196
226
|
* If string, then accesses each element at that key to get value.
|
|
197
227
|
* If function, then calls the callback on each element to get value.
|
|
198
228
|
* @param {V=} $1.cutoff Only values below cutoff will be considered.
|
|
199
|
-
* @returns {T}
|
|
229
|
+
* @returns {T|undefined}
|
|
200
230
|
*/
|
|
201
231
|
export function findMin(array, { key, cutoff = Infinity } = {}) {
|
|
202
232
|
let closest
|
|
@@ -229,7 +259,7 @@ export function findMin(array, { key, cutoff = Infinity } = {}) {
|
|
|
229
259
|
}
|
|
230
260
|
|
|
231
261
|
/**
|
|
232
|
-
* Find the maximum value in an array.
|
|
262
|
+
* Find the maximum value in an array. undefined or null values are ignored.
|
|
233
263
|
* @template T, V
|
|
234
264
|
* @param {Array<T>} array
|
|
235
265
|
* @param {Object} $1
|
|
@@ -237,7 +267,7 @@ export function findMin(array, { key, cutoff = Infinity } = {}) {
|
|
|
237
267
|
* If string, then accesses each element at that key to get value.
|
|
238
268
|
* If function, then calls the callback on each element to get value.
|
|
239
269
|
* @param {V=} $1.cutoff Only values above cutoff will be considered.
|
|
240
|
-
* @returns {T}
|
|
270
|
+
* @returns {T|undefined}
|
|
241
271
|
*/
|
|
242
272
|
export function findMax(array, { key, cutoff = -Infinity } = {}) {
|
|
243
273
|
let closest
|
package/src/find.test.js
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
import { describe, expect, it } from "@jest/globals"
|
|
3
3
|
|
|
4
4
|
const {
|
|
5
|
-
|
|
5
|
+
findEq,
|
|
6
|
+
findSmallestDiff,
|
|
6
7
|
findClosestLT,
|
|
7
8
|
findClosestLTE,
|
|
8
9
|
findClosestGT,
|
|
@@ -13,40 +14,75 @@ const {
|
|
|
13
14
|
findTruthy,
|
|
14
15
|
} = await import("./find.js")
|
|
15
16
|
|
|
16
|
-
describe("
|
|
17
|
+
describe("findEq", () => {
|
|
18
|
+
it("returns the first element equal to desired (no key)", () => {
|
|
19
|
+
expect(findEq([1, 2, 3, 2], 2)).toBe(2)
|
|
20
|
+
expect(findEq([1, 2, 3], 4)).toBeUndefined()
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
it("returns the first value from key function equal to desired", () => {
|
|
24
|
+
const arr = [{ v: 1 }, { v: 2 }, { v: 3 }]
|
|
25
|
+
expect(findEq(arr, 2, { key: (e) => e.v })).toBe(2)
|
|
26
|
+
expect(findEq(arr, 4, { key: (e) => e.v })).toBeUndefined()
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
it("returns the first value from key string equal to desired", () => {
|
|
30
|
+
const arr = [{ x: 1 }, { x: 2 }, { x: 3 }]
|
|
31
|
+
expect(findEq(arr, 2, { key: "x" })).toBe(2)
|
|
32
|
+
expect(findEq(arr, 4, { key: "x" })).toBeUndefined()
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
it("returns the first value from key number equal to desired", () => {
|
|
36
|
+
const arr = [[1], [2], [3]]
|
|
37
|
+
expect(findEq(arr, 2, { key: 0 })).toBe(2)
|
|
38
|
+
expect(findEq(arr, 4, { key: 0 })).toBeUndefined()
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
it("returns undefined for empty array", () => {
|
|
42
|
+
expect(findEq([], 1)).toBeUndefined()
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
it("returns first matching value if there are duplicates", () => {
|
|
46
|
+
expect(findEq([2, 2, 3], 2)).toBe(2)
|
|
47
|
+
const arr = [{ v: 2 }, { v: 2 }]
|
|
48
|
+
expect(findEq(arr, 2, { key: (e) => e.v })).toBe(2)
|
|
49
|
+
})
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
describe("findSmallestDiff", () => {
|
|
17
53
|
it("returns the element closest in absolute value to desired", () => {
|
|
18
|
-
expect(
|
|
19
|
-
expect(
|
|
20
|
-
expect(
|
|
54
|
+
expect(findSmallestDiff([1, 5, 9], 6)).toBe(5)
|
|
55
|
+
expect(findSmallestDiff([1, 5, 9], 8)).toBe(9)
|
|
56
|
+
expect(findSmallestDiff([1, 5, 9], 1)).toBe(1)
|
|
21
57
|
})
|
|
22
58
|
|
|
23
59
|
it("returns the first element in case of tie", () => {
|
|
24
|
-
expect(
|
|
60
|
+
expect(findSmallestDiff([4, 8], 6)).toBe(4)
|
|
25
61
|
})
|
|
26
62
|
|
|
27
63
|
it("returns undefined for empty array", () => {
|
|
28
|
-
expect(
|
|
64
|
+
expect(findSmallestDiff([], 10)).toBeUndefined()
|
|
29
65
|
})
|
|
30
66
|
|
|
31
67
|
it("supports key as function", () => {
|
|
32
68
|
const arr = [{ v: 2 }, { v: 8 }]
|
|
33
|
-
expect(
|
|
69
|
+
expect(findSmallestDiff(arr, 5, { key: (e) => e.v })).toEqual({ v: 2 })
|
|
34
70
|
})
|
|
35
71
|
|
|
36
72
|
it("supports key as string", () => {
|
|
37
73
|
const arr = [{ x: 1 }, { x: 10 }]
|
|
38
|
-
expect(
|
|
74
|
+
expect(findSmallestDiff(arr, 8, { key: "x" })).toEqual({ x: 10 })
|
|
39
75
|
})
|
|
40
76
|
|
|
41
77
|
it("supports key as number", () => {
|
|
42
78
|
const arr = [[2], [8]]
|
|
43
|
-
expect(
|
|
79
|
+
expect(findSmallestDiff(arr, 7, { key: 0 })).toEqual([8])
|
|
44
80
|
})
|
|
45
81
|
|
|
46
82
|
it("respects cutoff", () => {
|
|
47
|
-
expect(
|
|
48
|
-
expect(
|
|
49
|
-
expect(
|
|
83
|
+
expect(findSmallestDiff([1, 5, 9], 6, { cutoff: 2 })).toBe(5)
|
|
84
|
+
expect(findSmallestDiff([1, 5, 9], 6, { cutoff: 1 })).toBe(5)
|
|
85
|
+
expect(findSmallestDiff([1, 5, 9], 6, { cutoff: 0 })).toBeUndefined()
|
|
50
86
|
})
|
|
51
87
|
})
|
|
52
88
|
|
|
@@ -200,7 +236,7 @@ describe("findClosestGTE", () => {
|
|
|
200
236
|
})
|
|
201
237
|
|
|
202
238
|
describe("findClosest", () => {
|
|
203
|
-
it("defaults to
|
|
239
|
+
it("defaults to diff comparator", () => {
|
|
204
240
|
expect(findClosest([1, 5, 9], 6)).toBe(5)
|
|
205
241
|
})
|
|
206
242
|
|
|
@@ -209,7 +245,9 @@ describe("findClosest", () => {
|
|
|
209
245
|
expect(findClosest([1, 5, 9], 6, { comparator: "lte" })).toBe(5)
|
|
210
246
|
expect(findClosest([1, 5, 9], 6, { comparator: "gt" })).toBe(9)
|
|
211
247
|
expect(findClosest([1, 5, 9], 6, { comparator: "gte" })).toBe(9)
|
|
212
|
-
expect(findClosest([1, 5, 9], 6, { comparator: "
|
|
248
|
+
expect(findClosest([1, 5, 9], 6, { comparator: "diff" })).toBe(5)
|
|
249
|
+
expect(findClosest([1, 5, 9], 6, { comparator: "eq" })).toBeUndefined()
|
|
250
|
+
expect(findClosest([1, 5, 9], 5, { comparator: "eq" })).toBe(5)
|
|
213
251
|
})
|
|
214
252
|
|
|
215
253
|
it("throws on unknown comparator", () => {
|
|
@@ -220,7 +258,8 @@ describe("findClosest", () => {
|
|
|
220
258
|
|
|
221
259
|
it("passes options to underlying function", () => {
|
|
222
260
|
const arr = [{ x: 1 }, { x: 10 }]
|
|
223
|
-
expect(findClosest(arr, 8, { comparator: "
|
|
261
|
+
expect(findClosest(arr, 8, { comparator: "diff", key: "x" })).toEqual({ x: 10 })
|
|
262
|
+
expect(findClosest(arr, 10, { comparator: "eq", key: "x" })).toBe(10)
|
|
224
263
|
})
|
|
225
264
|
})
|
|
226
265
|
|
package/src/math.js
CHANGED
package/src/math.test.js
CHANGED
|
@@ -311,9 +311,9 @@ describe("isNumber", () => {
|
|
|
311
311
|
expect(isNumber(Number.MIN_SAFE_INTEGER)).toBe(true)
|
|
312
312
|
})
|
|
313
313
|
|
|
314
|
-
it("returns
|
|
315
|
-
expect(isNumber(Infinity)).toBe(
|
|
316
|
-
expect(isNumber(-Infinity)).toBe(
|
|
314
|
+
it("returns false for Infinity and -Infinity", () => {
|
|
315
|
+
expect(isNumber(Infinity)).toBe(false)
|
|
316
|
+
expect(isNumber(-Infinity)).toBe(false)
|
|
317
317
|
})
|
|
318
318
|
|
|
319
319
|
it("returns false for NaN", () => {
|