@tim-code/my-util 0.2.0 → 0.2.1

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tim-code/my-util",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "author": "",
package/src/find.js CHANGED
@@ -185,3 +185,85 @@ export function findClosest(array, value, options = {}) {
185
185
  throw new Error(`Unknown comparator: ${comparator}`)
186
186
  }
187
187
  }
188
+
189
+ /**
190
+ * Find the minimum value in an array.
191
+ * @template T, V
192
+ * @param {Array<T>} array
193
+ * @param {Object} $1
194
+ * @param {string|Function=} $1.key Specifies an alternative to using each element as the value.
195
+ * If string, then accesses each element at that key to get value.
196
+ * If function, then calls the callback on each element to get value.
197
+ * @param {V=} $1.cutoff Only values below cutoff will be considered.
198
+ * @returns {T}
199
+ */
200
+ export function findMin(array, { key, cutoff = Infinity } = {}) {
201
+ let closest
202
+ if (typeof key === "function") {
203
+ for (let i = 0; i < array.length; i++) {
204
+ const element = array[i]
205
+ const value = key(element, i, array)
206
+ if (value < cutoff) {
207
+ closest = element
208
+ cutoff = value
209
+ }
210
+ }
211
+ } else if (typeof key === "number" || typeof key === "string") {
212
+ for (const element of array) {
213
+ const value = element[key]
214
+ if (value < cutoff) {
215
+ closest = element
216
+ cutoff = value
217
+ }
218
+ }
219
+ } else {
220
+ for (const value of array) {
221
+ if (value < cutoff) {
222
+ closest = value
223
+ cutoff = value
224
+ }
225
+ }
226
+ }
227
+ return closest
228
+ }
229
+
230
+ /**
231
+ * Find the maximum value in an array.
232
+ * @template T, V
233
+ * @param {Array<T>} array
234
+ * @param {Object} $1
235
+ * @param {string|Function=} $1.key Specifies an alternative to using each element as the value.
236
+ * If string, then accesses each element at that key to get value.
237
+ * If function, then calls the callback on each element to get value.
238
+ * @param {V=} $1.cutoff Only values above cutoff will be considered.
239
+ * @returns {T}
240
+ */
241
+ export function findMax(array, { key, cutoff = -Infinity } = {}) {
242
+ let closest
243
+ if (typeof key === "function") {
244
+ for (let i = 0; i < array.length; i++) {
245
+ const element = array[i]
246
+ const value = key(element, i, array)
247
+ if (value > cutoff) {
248
+ closest = element
249
+ cutoff = value
250
+ }
251
+ }
252
+ } else if (typeof key === "number" || typeof key === "string") {
253
+ for (const element of array) {
254
+ const value = element[key]
255
+ if (value > cutoff) {
256
+ closest = element
257
+ cutoff = value
258
+ }
259
+ }
260
+ } else {
261
+ for (const value of array) {
262
+ if (value > cutoff) {
263
+ closest = value
264
+ cutoff = value
265
+ }
266
+ }
267
+ }
268
+ return closest
269
+ }
package/src/find.test.js CHANGED
@@ -7,6 +7,8 @@ const {
7
7
  findClosestGT,
8
8
  findClosestGTE,
9
9
  findClosest,
10
+ findMin,
11
+ findMax,
10
12
  } = await import("./find.js")
11
13
 
12
14
  describe("findClosestAbs", () => {
@@ -214,3 +216,71 @@ describe("findClosest", () => {
214
216
  expect(findClosest(arr, 8, { comparator: "abs", key: "x" })).toEqual({ x: 10 })
215
217
  })
216
218
  })
219
+
220
+ describe("findMin", () => {
221
+ it("returns the minimum value in a numeric array", () => {
222
+ expect(findMin([3, 1, 4, 2])).toBe(1)
223
+ })
224
+
225
+ it("returns undefined for empty array", () => {
226
+ expect(findMin([])).toBeUndefined()
227
+ })
228
+
229
+ it("returns the first minimum if there are duplicates", () => {
230
+ expect(findMin([2, 1, 1, 3])).toBe(1)
231
+ })
232
+
233
+ it("supports key as function", () => {
234
+ const arr = [{ v: 5 }, { v: 2 }, { v: 8 }]
235
+ expect(findMin(arr, { key: (e) => e.v })).toEqual({ v: 2 })
236
+ })
237
+
238
+ it("supports key as string", () => {
239
+ const arr = [{ x: 5 }, { x: 2 }, { x: 8 }]
240
+ expect(findMin(arr, { key: "x" })).toEqual({ x: 2 })
241
+ })
242
+
243
+ it("supports key as number", () => {
244
+ const arr = [[5], [2], [8]]
245
+ expect(findMin(arr, { key: 0 })).toEqual([2])
246
+ })
247
+
248
+ it("respects cutoff", () => {
249
+ expect(findMin([3, 1, 4, 2], { cutoff: 2 })).toBe(1)
250
+ expect(findMin([3, 1, 4, 2], { cutoff: 1 })).toBeUndefined()
251
+ })
252
+ })
253
+
254
+ describe("findMax", () => {
255
+ it("returns the maximum value in a numeric array", () => {
256
+ expect(findMax([3, 1, 4, 2])).toBe(4)
257
+ })
258
+
259
+ it("returns undefined for empty array", () => {
260
+ expect(findMax([])).toBeUndefined()
261
+ })
262
+
263
+ it("returns the first maximum if there are duplicates", () => {
264
+ expect(findMax([4, 2, 4, 1])).toBe(4)
265
+ })
266
+
267
+ it("supports key as function", () => {
268
+ const arr = [{ v: 5 }, { v: 2 }, { v: 8 }]
269
+ expect(findMax(arr, { key: (e) => e.v })).toEqual({ v: 8 })
270
+ })
271
+
272
+ it("supports key as string", () => {
273
+ const arr = [{ x: 5 }, { x: 2 }, { x: 8 }]
274
+ expect(findMax(arr, { key: "x" })).toEqual({ x: 8 })
275
+ })
276
+
277
+ it("supports key as number", () => {
278
+ const arr = [[5], [2], [8]]
279
+ expect(findMax(arr, { key: 0 })).toEqual([8])
280
+ })
281
+
282
+ it("respects cutoff", () => {
283
+ expect(findMax([3, 1, 4, 2], { cutoff: 2 })).toBe(4)
284
+ expect(findMax([3, 1, 4, 2], { cutoff: 4 })).toBeUndefined()
285
+ })
286
+ })