diff --git a/collections/max_by.ts b/collections/max_by.ts index 968875e2d824..9ca8d5e1b595 100644 --- a/collections/max_by.ts +++ b/collections/max_by.ts @@ -137,16 +137,41 @@ export function maxBy( | ((el: T) => bigint) | ((el: T) => Date), ): T | undefined { - let max: T | undefined; - let maxValue: ReturnType | undefined; + if (Array.isArray(array)) { + const length = array.length; + if (length === 0) return undefined; - for (const current of array) { - const currentValue = selector(current); + let max: T = array[0]!; + let maxValue = selector(max); - if (maxValue === undefined || currentValue > maxValue) { - max = current; + for (let i = 1; i < length; i++) { + const current = array[i]!; + const currentValue = selector(current); + if (currentValue > maxValue) { + max = current; + maxValue = currentValue; + } + } + + return max; + } + + const iter = array[Symbol.iterator](); + const first = iter.next(); + + if (first.done) return undefined; + + let max: T = first.value; + let maxValue = selector(max); + + let next = iter.next(); + while (!next.done) { + const currentValue = selector(next.value); + if (currentValue > maxValue) { + max = next.value; maxValue = currentValue; } + next = iter.next(); } return max; diff --git a/collections/max_by_test.ts b/collections/max_by_test.ts index e5b4b95a0e83..c57f8cfedcdb 100644 --- a/collections/max_by_test.ts +++ b/collections/max_by_test.ts @@ -1,6 +1,6 @@ // Copyright 2018-2025 the Deno authors. MIT license. -import { assertEquals } from "@std/assert"; +import { assertEquals, assertStrictEquals } from "@std/assert"; import { maxBy } from "./max_by.ts"; Deno.test("maxBy() handles array input", () => { @@ -40,6 +40,10 @@ Deno.test("maxBy() handles array input with multiple max", () => { assertEquals(max, { name: "John", age: 42 }); }); +Deno.test("maxBy() handles single element array", () => { + assertEquals(maxBy([42], (i) => i), 42); +}); + Deno.test("maxBy() handles array of positive numbers", () => { const input = [2, 3, 5]; @@ -72,6 +76,18 @@ Deno.test("maxBy() handles of empty array", () => { assertEquals(max, undefined); }); +Deno.test("maxBy() handles empty input", () => { + const emptyArray: Array<{ age: number }> = []; + const max = maxBy(emptyArray, (it) => it.age); + + assertEquals(max, undefined); +}); + +Deno.test("maxBy() handles empty generator", () => { + function* gen(): Generator {} + assertEquals(maxBy(gen(), (i) => i), undefined); +}); + Deno.test("maxBy() handles array of numbers with multiple max", () => { const input = [2, 3, 5, 5]; @@ -96,6 +112,12 @@ Deno.test("maxBy() handles array of numbers with NaN", () => { assertEquals(max, 5); }); +Deno.test("maxBy() handles NaN at first position", () => { + const input = [NaN, 2, 3]; + const max = maxBy(input, (i) => i); + assertEquals(max, NaN); +}); + Deno.test("maxBy() handles no mutation", () => { const input = [2, 3, 5]; @@ -104,11 +126,11 @@ Deno.test("maxBy() handles no mutation", () => { assertEquals(input, [2, 3, 5]); }); -Deno.test("maxBy() handles empty input", () => { - const emptyArray: Array<{ age: number }> = []; - const max = maxBy(emptyArray, (it) => it.age); - - assertEquals(max, undefined); +Deno.test("maxBy() returns same object reference", () => { + const john = { name: "John", age: 42 }; + const input = [{ name: "Kyle", age: 34 }, john, { name: "Anna", age: 23 }]; + const max = maxBy(input, (i) => i.age); + assertStrictEquals(max, john); }); Deno.test({ @@ -136,3 +158,36 @@ Deno.test({ assertEquals(maxBy(input, (it) => new Date(it)), "February 1, 2022"); }, }); + +Deno.test("maxBy() handles generator input", () => { + function* gen() { + yield { name: "Kyle", age: 34 }; + yield { name: "John", age: 42 }; + yield { name: "Anna", age: 23 }; + } + const max = maxBy(gen(), (i) => i.age); + assertEquals(max, { name: "John", age: 42 }); +}); + +Deno.test("maxBy() handles single element generator", () => { + function* gen() { + yield 42; + } + assertEquals(maxBy(gen(), (i) => i), 42); +}); + +Deno.test("maxBy() handles Set input", () => { + const input = new Set([5, 2, 8, 1, 9]); + const max = maxBy(input, (i) => i); + assertEquals(max, 9); +}); + +Deno.test("maxBy() handles Map values", () => { + const input = new Map([ + ["a", { age: 34 }], + ["b", { age: 23 }], + ["c", { age: 45 }], + ]); + const max = maxBy(input.values(), (i) => i.age); + assertEquals(max, { age: 45 }); +}); diff --git a/collections/min_by.ts b/collections/min_by.ts index dee32c2ee4df..93a1c042815f 100644 --- a/collections/min_by.ts +++ b/collections/min_by.ts @@ -135,16 +135,41 @@ export function minBy( | ((el: T) => bigint) | ((el: T) => Date), ): T | undefined { - let min: T | undefined; - let minValue: ReturnType | undefined; + if (Array.isArray(array)) { + const length = array.length; + if (length === 0) return undefined; - for (const current of array) { - const currentValue = selector(current); + let min: T = array[0]!; + let minValue = selector(min); - if (minValue === undefined || currentValue < minValue) { - min = current; + for (let i = 1; i < length; i++) { + const current = array[i]!; + const currentValue = selector(current); + if (currentValue < minValue) { + min = current; + minValue = currentValue; + } + } + + return min; + } + + const iter = array[Symbol.iterator](); + const first = iter.next(); + + if (first.done) return undefined; + + let min: T = first.value; + let minValue = selector(min); + + let next = iter.next(); + while (!next.done) { + const currentValue = selector(next.value); + if (currentValue < minValue) { + min = next.value; minValue = currentValue; } + next = iter.next(); } return min; diff --git a/collections/min_by_test.ts b/collections/min_by_test.ts index b52c338e411c..c9f0b1459e11 100644 --- a/collections/min_by_test.ts +++ b/collections/min_by_test.ts @@ -1,6 +1,6 @@ // Copyright 2018-2025 the Deno authors. MIT license. -import { assertEquals } from "@std/assert"; +import { assertEquals, assertStrictEquals } from "@std/assert"; import { minBy } from "./min_by.ts"; Deno.test("minBy() handles array input", () => { @@ -40,6 +40,10 @@ Deno.test("minBy() handles array input with multiple min", () => { assertEquals(min, { name: "Anna", age: 23 }); }); +Deno.test("minBy() handles single element array", () => { + assertEquals(minBy([42], (i) => i), 42); +}); + Deno.test("minBy() handles array of positive numbers", () => { const input = [2, 3, 5]; @@ -72,6 +76,19 @@ Deno.test("minBy() handles of empty array", () => { assertEquals(min, undefined); }); +Deno.test("minBy() handles empty input", () => { + const input: Array<{ age: number }> = []; + + const min = minBy(input, (i) => i.age); + + assertEquals(min, undefined); +}); + +Deno.test("minBy() handles empty generator", () => { + function* gen(): Generator {} + assertEquals(minBy(gen(), (i) => i), undefined); +}); + Deno.test("minBy() handles array of numbers with multiple min", () => { const input = [2, 3, 5, 5]; @@ -96,6 +113,12 @@ Deno.test("minBy() handles array of numbers with NaN", () => { assertEquals(min, 2); }); +Deno.test("minBy() handles NaN at first position", () => { + const input = [NaN, 2, 3]; + const min = minBy(input, (i) => i); + assertEquals(min, NaN); +}); + Deno.test("minBy() handles no mutation", () => { const input = [2, 3, 5, NaN]; @@ -104,12 +127,11 @@ Deno.test("minBy() handles no mutation", () => { assertEquals(input, [2, 3, 5, NaN]); }); -Deno.test("minBy() handles empty input", () => { - const input: Array<{ age: number }> = []; - +Deno.test("minBy() returns same object reference", () => { + const anna = { name: "Anna", age: 23 }; + const input = [{ name: "Kyle", age: 34 }, anna, { name: "John", age: 42 }]; const min = minBy(input, (i) => i.age); - - assertEquals(min, undefined); + assertStrictEquals(min, anna); }); Deno.test({ @@ -137,3 +159,36 @@ Deno.test({ assertEquals(minBy(input, (it) => new Date(it)), "December 17, 1995"); }, }); + +Deno.test("minBy() handles generator input", () => { + function* gen() { + yield { name: "Kyle", age: 34 }; + yield { name: "John", age: 42 }; + yield { name: "Anna", age: 23 }; + } + const min = minBy(gen(), (i) => i.age); + assertEquals(min, { name: "Anna", age: 23 }); +}); + +Deno.test("minBy() handles single element generator", () => { + function* gen() { + yield 42; + } + assertEquals(minBy(gen(), (i) => i), 42); +}); + +Deno.test("minBy() handles Set input", () => { + const input = new Set([5, 2, 8, 1, 9]); + const min = minBy(input, (i) => i); + assertEquals(min, 1); +}); + +Deno.test("minBy() handles Map values", () => { + const input = new Map([ + ["a", { age: 34 }], + ["b", { age: 23 }], + ["c", { age: 45 }], + ]); + const min = minBy(input.values(), (i) => i.age); + assertEquals(min, { age: 23 }); +});