diff --git a/collections/sort_by.ts b/collections/sort_by.ts new file mode 100644 index 000000000000..524da8329839 --- /dev/null +++ b/collections/sort_by.ts @@ -0,0 +1,49 @@ +// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. + +/** + * Returns all elements in the given collection, sorted by their result using the given selector + * + * Example: + * + * ```ts + * import { sortBy } from "./sort_by.ts" + * + * const people = [ + * { name: 'Anna', age: 34 }, + * { name: 'Kim', age: 42 }, + * { name: 'John', age: 23 }, + * ] + * const sortedByAge = sortBy(people, it => it.age) + * + * console.assert(sortedByAge === [ + * { name: 'John', age: 23 }, + * { name: 'Anna', age: 34 }, + * { name: 'Kim', age: 42 }, + * ]) + * ``` + */ +export function sortBy( + array: Array, + selector: + | ((el: T) => number) + | ((el: T) => string) + | ((el: T) => bigint) + | ((el: T) => Date), +): Array { + const ret = Array.from(array); + + return ret.sort((a, b) => { + const selectedA = selector(a); + const selectedB = selector(b); + + if (selectedA > selectedB) { + return 1; + } + + if (selectedA < selectedB) { + return -1; + } + + return 0; + }); +} diff --git a/collections/sort_by_test.ts b/collections/sort_by_test.ts new file mode 100644 index 000000000000..da0efebc5479 --- /dev/null +++ b/collections/sort_by_test.ts @@ -0,0 +1,104 @@ +// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. + +import { assertEquals } from "../testing/asserts.ts"; +import { sortBy } from "./sort_by.ts"; + +function sortByTest( + input: [ + Array, + | ((el: T) => number) + | ((el: T) => string) + | ((el: T) => bigint) + | ((el: T) => Date), + ], + expected: Array, + message?: string, +) { + const actual = sortBy(...input); + assertEquals(actual, expected, message); +} + +Deno.test({ + name: "[collections/sortBy] no mutation", + fn() { + const array = ["a", "abc", "ba"]; + sortBy(array, (it) => it.length); + + assertEquals(array, ["a", "abc", "ba"]); + }, +}); + +Deno.test({ + name: "[collections/sortBy] empty input", + fn() { + sortByTest( + [[], () => 5], + [], + ); + }, +}); + +Deno.test({ + name: "[collections/sortBy] identity selector", + fn() { + sortByTest( + [ + [2, 3, 1], + (it) => it, + ], + [1, 2, 3], + ); + }, +}); + +Deno.test({ + name: "[collections/sortBy] sortings", + fn() { + const testArray = [ + { name: "benchmark", stage: 3 }, + { name: "test", stage: 2 }, + { name: "build", stage: 1 }, + { name: "deploy", stage: 4 }, + ]; + + sortByTest( + [ + testArray, + (it) => it.stage, + ], + [ + { name: "build", stage: 1 }, + { name: "test", stage: 2 }, + { name: "benchmark", stage: 3 }, + { name: "deploy", stage: 4 }, + ], + ); + sortByTest( + [ + testArray, + (it) => it.name, + ], + [ + { name: "benchmark", stage: 3 }, + { name: "build", stage: 1 }, + { name: "deploy", stage: 4 }, + { name: "test", stage: 2 }, + ], + ); + sortByTest( + [ + [ + "February 1, 2022", + "December 17, 1995", + "June 12, 2012", + ], + (it) => new Date(it), + ], + [ + "December 17, 1995", + "June 12, 2012", + "February 1, 2022", + ], + ); + }, +});