All files / collections / min_of.ts

96.55% Branches 28/29
100.00% Functions 1/1
97.22% Lines 35/36
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
x5
 
 
 
 
 
x5
x5
 
x20
x17
x17
 
x16
x17
 
x17
x48
x48
x5
x48
x1
x1
x48
 
x14
x14
 
x3
x3
x3
 
x17
 
x2
 
 
x2
x17
x4
x4
x2
x2
x1
x1
x3
x3
 
x1
x20




















































































































I













// Copyright 2018-2026 the Deno authors. MIT license.
// This module is browser compatible.

/**
 * Applies the given selector to all elements of the given collection and
 * returns the min value of all elements. If an empty array is provided the
 * function will return undefined.
 *
 * @typeParam T The type of the elements in the array.
 *
 * @param array The array to find the minimum element in.
 * @param selector The function to get the value to compare from each element.
 * The function receives the element and its index.
 *
 * @returns The smallest value of the given function or undefined if there are
 * no elements.
 *
 * @example Basic usage
 * ```ts
 * import { minOf } from "@std/collections/min-of";
 * import { assertEquals } from "@std/assert";
 *
 * const inventory = [
 *   { name: "mustard", count: 2 },
 *   { name: "soy", count: 4 },
 *   { name: "tomato", count: 32 },
 * ];
 *
 * const minCount = minOf(inventory, (item) => item.count);
 *
 * assertEquals(minCount, 2);
 * ```
 *
 * @example Using the index parameter
 * ```ts
 * import { minOf } from "@std/collections/min-of";
 * import { assertEquals } from "@std/assert";
 *
 * const array = [4, 3, 2, 1];
 * const result = minOf(array, (_, index) => index);
 *
 * assertEquals(result, 0);
 * ```
 */
export function minOf<T>(
  array: Iterable<T>,
  selector: (el: T, index: number) => number,
): number | undefined;
/**
 * Applies the given selector to all elements of the given collection and
 * returns the min value of all elements. If an empty array is provided the
 * function will return undefined.
 *
 * @typeParam T The type of the elements in the array.
 *
 * @param array The array to find the minimum element in.
 * @param selector The function to get the value to compare from each element.
 * The function receives the element and its index.
 *
 * @returns The first element that is the smallest value of the given function
 * or undefined if there are no elements.
 *
 * @example Basic usage
 * ```ts
 * import { minOf } from "@std/collections/min-of";
 * import { assertEquals } from "@std/assert";
 *
 * const inventory = [
 *   { name: "mustard", count: 2n },
 *   { name: "soy", count: 4n },
 *   { name: "tomato", count: 32n },
 * ];
 *
 * const minCount = minOf(inventory, (item) => item.count);
 *
 * assertEquals(minCount, 2n);
 * ```
 */
export function minOf<T>(
  array: Iterable<T>,
  selector: (el: T, index: number) => bigint,
): bigint | undefined;
export function minOf<
  T,
  S extends
    | ((el: T, index: number) => number)
    | ((el: T, index: number) => bigint),
>(
  array: Iterable<T>,
  selector: S,
): ReturnType<S> | undefined {
  if (Array.isArray(array)) {
    const length = array.length;
    if (length === 0) return undefined;

    let min = selector(array[0]!, 0) as ReturnType<S>;
    if (Number.isNaN(min)) return min;

    for (let i = 1; i < length; i++) {
      const currentValue = selector(array[i]!, i) as ReturnType<S>;
      if (currentValue < min) {
        min = currentValue;
      } else if (Number.isNaN(currentValue)) {
        return currentValue;
      }
    }

    return min;
  }

  let index = 0;
  const iter = array[Symbol.iterator]();
  const first = iter.next();

  if (first.done) return undefined;

  let min = selector(first.value, index++) as ReturnType<S>;
  if (Number.isNaN(min)) return min;

  let next = iter.next();
  while (!next.done) {
    const currentValue = selector(next.value, index++) as ReturnType<S>;
    if (currentValue < min) {
      min = currentValue;
    } else if (Number.isNaN(currentValue)) {
      return currentValue;
    }
    next = iter.next();
  }

  return min;
}