Skip to content

feat(collections/unstable): support iterators in sortBy() #5919

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Sep 23, 2024
Merged
1 change: 1 addition & 0 deletions collections/deno.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
"./take-last-while": "./take_last_while.ts",
"./take-while": "./take_while.ts",
"./union": "./union.ts",
"./unstable-sort-by": "./unstable_sort_by.ts",
"./unstable-take-while": "./unstable_take_while.ts",
"./unzip": "./unzip.ts",
"./without-all": "./without_all.ts",
Expand Down
3 changes: 3 additions & 0 deletions collections/sort_by.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ export type SortByOptions = {
* element. Ascending or descending order can be specified through the `order`
* option. By default, the elements are sorted in ascending order.
*
* Note: If you want to process any iterable, use the new version of
* `sortBy` from `@std/collections/unstable-sort-by`.
*
* @typeParam T The type of the array elements.
*
* @param array The array to sort.
Expand Down
253 changes: 253 additions & 0 deletions collections/sort_by_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import { assertEquals } from "@std/assert";
import { sortBy } from "./sort_by.ts";
import { sortBy as unstableSortBy } from "./unstable_sort_by.ts";

Deno.test({
name: "sortBy() handles no mutation",
Expand Down Expand Up @@ -221,3 +222,255 @@ Deno.test({
);
},
});

Deno.test({
name: "(unstable) sortBy() handles no mutation",
fn() {
const array = ["a", "abc", "ba"];
unstableSortBy(array, (it) => it.length);

assertEquals(array, ["a", "abc", "ba"]);
},
});

Deno.test({
name: "(unstable) sortBy() calls the selector function once",
fn() {
let callCount = 0;
const array = [0, 1, 2];
unstableSortBy(array, (it) => {
callCount++;
return it;
});

assertEquals(callCount, array.length);
},
});

Deno.test({
name: "(unstable) sortBy() handles empty input",
fn() {
assertEquals(unstableSortBy([], () => 5), []);
},
});

Deno.test({
name: "(unstable) sortBy() handles identity selector",
fn() {
assertEquals(unstableSortBy([2, 3, 1], (it) => it), [1, 2, 3]);
},
});

Deno.test({
name: "(unstable) sortBy() handles stable sort",
fn() {
assertEquals(
unstableSortBy([
{ id: 1, date: "February 1, 2022" },
{ id: 2, date: "December 17, 1995" },
{ id: 3, date: "June 12, 2012" },
{ id: 4, date: "December 17, 1995" },
{ id: 5, date: "June 12, 2012" },
], (it) => new Date(it.date)),
[
{ id: 2, date: "December 17, 1995" },
{ id: 4, date: "December 17, 1995" },
{ id: 3, date: "June 12, 2012" },
{ id: 5, date: "June 12, 2012" },
{ id: 1, date: "February 1, 2022" },
],
);

assertEquals(
unstableSortBy([
{ id: 1, str: "c" },
{ id: 2, str: "a" },
{ id: 3, str: "b" },
{ id: 4, str: "a" },
{ id: 5, str: "b" },
], (it) => it.str),
[
{ id: 2, str: "a" },
{ id: 4, str: "a" },
{ id: 3, str: "b" },
{ id: 5, str: "b" },
{ id: 1, str: "c" },
],
);
},
});

Deno.test({
name: "(unstable) sortBy() handles special number values",
fn() {
assertEquals(
unstableSortBy([
1,
Number.POSITIVE_INFINITY,
2,
Number.NEGATIVE_INFINITY,
3,
Number.NaN,
4,
Number.NaN,
], (it) => it),
[
Number.NEGATIVE_INFINITY,
1,
2,
3,
4,
Number.POSITIVE_INFINITY,
Number.NaN,
Number.NaN,
],
);

assertEquals(
unstableSortBy([
Number.NaN,
1,
Number.POSITIVE_INFINITY,
Number.NaN,
7,
Number.NEGATIVE_INFINITY,
Number.NaN,
2,
6,
5,
9,
], (it) => it),
[
Number.NEGATIVE_INFINITY,
1,
2,
5,
6,
7,
9,
Number.POSITIVE_INFINITY,
Number.NaN,
Number.NaN,
Number.NaN,
],
);

// Test that NaN sort is stable.
const nanArray = [
{ id: 1, nan: Number.NaN },
{ id: 2, nan: Number.NaN },
{ id: 3, nan: Number.NaN },
{ id: 4, nan: Number.NaN },
];
assertEquals(unstableSortBy(nanArray, ({ nan }) => nan), nanArray);
},
});

Deno.test({
name: "(unstable) sortBy() handles sortings",
fn() {
const testArray = [
{ name: "benchmark", stage: 3 },
{ name: "test", stage: 2 },
{ name: "build", stage: 1 },
{ name: "deploy", stage: 4 },
];

assertEquals(unstableSortBy(testArray, (it) => it.stage), [
{ name: "build", stage: 1 },
{ name: "test", stage: 2 },
{ name: "benchmark", stage: 3 },
{ name: "deploy", stage: 4 },
]);

assertEquals(unstableSortBy(testArray, (it) => it.name), [
{ name: "benchmark", stage: 3 },
{ name: "build", stage: 1 },
{ name: "deploy", stage: 4 },
{ name: "test", stage: 2 },
]);

assertEquals(
unstableSortBy([
"9007199254740999",
"9007199254740991",
"9007199254740995",
], (it) => BigInt(it)),
[
"9007199254740991",
"9007199254740995",
"9007199254740999",
],
);

assertEquals(
unstableSortBy([
"February 1, 2022",
"December 17, 1995",
"June 12, 2012",
], (it) => new Date(it)),
[
"December 17, 1995",
"June 12, 2012",
"February 1, 2022",
],
);
},
});

Deno.test({
name: "(unstable) sortBy() handles desc ordering",
fn() {
assertEquals(
unstableSortBy(
[
"January 27, 1995",
"November 26, 2020",
"June 17, 1952",
"July 15, 1993",
],
(it) => new Date(it),
{ order: "desc" },
),
[
"November 26, 2020",
"January 27, 1995",
"July 15, 1993",
"June 17, 1952",
],
);
},
});

Deno.test({
name: "(unstable) sortBy() works with iterators",
fn() {
const set = new Set([10, 312, 99, 5.45, 100, -3, 4.6]);

assertEquals(
unstableSortBy(set, (it) => it),
[-3, 4.6, 5.45, 10, 99, 100, 312],
);
assertEquals(
unstableSortBy(set, (it) => it, { order: "desc" }),
[312, 100, 99, 10, 5.45, 4.6, -3],
);

const map = new Map([
["a", 2],
["c", 1],
["b", 3],
]);

assertEquals(unstableSortBy(map, (it) => it[0]), [
["a", 2],
["b", 3],
["c", 1],
]);
assertEquals(unstableSortBy(map, (it) => it[1], { order: "desc" }), [
["b", 3],
["a", 2],
["c", 1],
]);
},
});
Loading