From c32f8450eee8dcd9c6844db2064703c7daf4afb5 Mon Sep 17 00:00:00 2001 From: Mikael Couzic Date: Tue, 29 Mar 2022 19:36:46 +0200 Subject: [PATCH 1/3] Enable sorting by key --- src/Sequence.ts | 8 ++++---- src/asSelector.ts | 7 +++++++ src/createComparatorFactory.ts | 7 +------ src/sortedBy.ts | 19 +++++++++++++++++-- src/sortedByDescending.ts | 20 +++++++++++++++++--- 5 files changed, 46 insertions(+), 15 deletions(-) create mode 100644 src/asSelector.ts diff --git a/src/Sequence.ts b/src/Sequence.ts index 76eb3c3..960ec68 100644 --- a/src/Sequence.ts +++ b/src/Sequence.ts @@ -54,8 +54,8 @@ import {Reverse} from "./reverse"; import {Single} from "./single"; import {SingleOrNull} from "./singleOrNull"; import {Sorted} from "./sorted"; -import {SortedBy} from "./sortedBy"; -import {SortedByDescending} from "./sortedByDescending"; +import {SortedBy, SortedByOperator} from "./sortedBy"; +import {SortedByDescending, SortedByDescendingOperator} from "./sortedByDescending"; import {SortedDescending} from "./sortedDescending"; import {SortedWith} from "./sortedWith"; import {Sum} from "./sum"; @@ -89,8 +89,8 @@ export default Sequence; export interface SequenceOperators extends All, Any, AsIterable, Associate, AssociateBy, Average, Chunk, Contains, Count, Distinct, DistinctBy, Drop, DropWhile, ElementAt, ElementAtOrElse, ElementAtOrNull, Filter, FilterIndexed, FilterNot, FilterNotNull, First, FirstOrNull, FlatMap, Flatten, Fold, FoldIndexed, ForEach, ForEachIndexed, GroupBy, IndexOf, IndexOfFirst, IndexOfLast, JoinToString, Last, LastOrNull, Map, MapIndexed, MapNotNull, Max, MaxBy, MaxWith, Merge, Min, MinBy, - Minus, MinWith, None, OnEach, Partition, Plus, Reduce, ReduceIndexed, Reverse, Single, SingleOrNull, Sorted, SortedBy, SortedByDescending, SortedDescending, SortedWith, - Sum, SumBy, Take, TakeWhile, ToArray, ToMap, ToSet, Unzip, WithIndex, Zip { + Minus, MinWith, None, OnEach, Partition, Plus, Reduce, ReduceIndexed, Reverse, Single, SingleOrNull, Sorted, SortedByOperator, SortedByDescendingOperator, SortedDescending, + SortedWith, Sum, SumBy, Take, TakeWhile, ToArray, ToMap, ToSet, Unzip, WithIndex, Zip { } class SequenceImpl { diff --git a/src/asSelector.ts b/src/asSelector.ts new file mode 100644 index 0000000..9465d19 --- /dev/null +++ b/src/asSelector.ts @@ -0,0 +1,7 @@ +export function asSelector( + keyOrSelector: keyof T | ((item: T) => any) +) { + return typeof keyOrSelector === "function" + ? keyOrSelector + : (item: T) => item[keyOrSelector]; +} diff --git a/src/createComparatorFactory.ts b/src/createComparatorFactory.ts index 75ec057..cd54c4f 100644 --- a/src/createComparatorFactory.ts +++ b/src/createComparatorFactory.ts @@ -1,3 +1,4 @@ +import { asSelector } from "./asSelector"; import ComparatorFactory from "./ComparatorFactory"; import Comparator from "./Comparator"; @@ -55,12 +56,6 @@ function compareByDescending(keyOrSelector: any): Comparator { ); } -function asSelector(keyOrSelector: (item: T) => any | string): (item: T) => any { - return typeof keyOrSelector === "function" - ? keyOrSelector - : (item: T) => (item as any)[keyOrSelector as string]; -} - function naturalCompare(a: T, b: T): number { return a < b ? -1 : a > b ? 1 : 0; } diff --git a/src/sortedBy.ts b/src/sortedBy.ts index 26412a2..d97f85f 100644 --- a/src/sortedBy.ts +++ b/src/sortedBy.ts @@ -1,6 +1,7 @@ +import { asSelector } from "./asSelector"; import Sequence from "./Sequence"; -export class SortedBy { +export interface SortedByOperator { /** * Returns a new sequence with all elements sorted ascending by the value specified @@ -9,7 +10,21 @@ export class SortedBy { * @param {(value: T) => R} selector * @returns {Sequence} */ - sortedBy(this: Sequence, selector: (value: T) => R): Sequence { + sortedBy(this: Sequence, selector: (value: T) => R): Sequence; + + /** + * Returns a new sequence with all elements sorted in ascending order of values for the given `key`. + * + * @param {keyof T} key + * @returns {Sequence} + */ + sortedBy(this: Sequence, key: keyof T): Sequence; +} + +export class SortedBy implements SortedByOperator { + + sortedBy(this:Sequence , keyOrSelector: keyof T | ((value:T) => any)): Sequence { + const selector = asSelector(keyOrSelector); return this.sorted(it => it.compareBy(selector)); } diff --git a/src/sortedByDescending.ts b/src/sortedByDescending.ts index 1a03761..110ac41 100644 --- a/src/sortedByDescending.ts +++ b/src/sortedByDescending.ts @@ -1,7 +1,7 @@ +import { asSelector } from "./asSelector"; import Sequence from "./Sequence"; -export class SortedByDescending { - +export interface SortedByDescendingOperator { /** * Returns a new sequence with all elements sorted descending by the value specified * by the given `selector` function. @@ -9,7 +9,21 @@ export class SortedByDescending { * @param {(value: T) => R} selector * @returns {Sequence} */ - sortedByDescending(this: Sequence, selector: (value: T) => R): Sequence { + sortedByDescending(this: Sequence, selector: (value: T) => R): Sequence; + + /** + * Returns a new sequence with all elements sorted in descending order of values for the given `key`. + * + * @param {keyof T} key + * @returns {Sequence} + */ + sortedByDescending(this: Sequence, key: keyof T): Sequence; +} + +export class SortedByDescending implements SortedByDescendingOperator { + + sortedByDescending(this: Sequence, keyOrSelector: keyof T | ((value: T) => any)): Sequence { + const selector = asSelector(keyOrSelector); return this.sorted(it => it.compareByDescending(selector)); } From 3d25786eceef45e6ef1d8726f1be3125910eaa56 Mon Sep 17 00:00:00 2001 From: Mikael Couzic Date: Tue, 29 Mar 2022 19:38:01 +0200 Subject: [PATCH 2/3] Add Comparator and ComparatorFactory to docs --- src/Sequence.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Sequence.ts b/src/Sequence.ts index 960ec68..9b2fe22 100644 --- a/src/Sequence.ts +++ b/src/Sequence.ts @@ -174,3 +174,6 @@ export function range(start: number, endInclusive: number, step: number = 1): Se } }); } + +export { default as Comparator } from "./Comparator"; +export { default as ComparatorFactory } from "./ComparatorFactory"; From c5e0c480ba9c97717bd40b77a32149f6156cb12a Mon Sep 17 00:00:00 2001 From: Mikael Couzic Date: Tue, 29 Mar 2022 19:49:34 +0200 Subject: [PATCH 3/3] Add tests for sorting by key --- test/sortedBy.test.ts | 18 +++++++++++++++++- test/sortedByDescending.test.ts | 20 ++++++++++++++++++-- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/test/sortedBy.test.ts b/test/sortedBy.test.ts index fc1b426..76e03a7 100644 --- a/test/sortedBy.test.ts +++ b/test/sortedBy.test.ts @@ -1,7 +1,7 @@ import {sequenceOf} from "../src/Sequence"; describe("sortedBy", () => { - it("should sort by the given key ascending", () => { + it("should sort in ascending order using a selector", () => { const a4 = {a: 4}; const a1 = {a: 1}; const a3 = {a: 3}; @@ -17,4 +17,20 @@ describe("sortedBy", () => { expect(array[2]).toBe(a4); expect(array[3]).toBe(a23); }); + it("should sort in ascending order using a key", () => { + const a4 = {a: 4}; + const a1 = {a: 1}; + const a3 = {a: 3}; + const a23 = {a: 23}; + + const array = sequenceOf(a4, a1, a3, a23) + .sortedBy("a") + .toArray(); + + expect(array.length).toBe(4); + expect(array[0]).toBe(a1); + expect(array[1]).toBe(a3); + expect(array[2]).toBe(a4); + expect(array[3]).toBe(a23); + }); }); \ No newline at end of file diff --git a/test/sortedByDescending.test.ts b/test/sortedByDescending.test.ts index 27fc2d8..4c4333b 100644 --- a/test/sortedByDescending.test.ts +++ b/test/sortedByDescending.test.ts @@ -1,7 +1,7 @@ import {sequenceOf} from "../src/Sequence"; -describe("sortedBy", () => { - it("should sort by the given key descending", () => { +describe("sortedByDescending", () => { + it("should sort in descending order using a selector", () => { const a4 = {a: 4}; const a1 = {a: 1}; const a3 = {a: 3}; @@ -17,4 +17,20 @@ describe("sortedBy", () => { expect(array[2]).toBe(a3); expect(array[3]).toBe(a1); }); + it("should sort in descending order using a key", () => { + const a4 = {a: 4}; + const a1 = {a: 1}; + const a3 = {a: 3}; + const a23 = {a: 23}; + + const array = sequenceOf(a4, a1, a3, a23) + .sortedByDescending("a") + .toArray(); + + expect(array.length).toBe(4); + expect(array[0]).toBe(a23); + expect(array[1]).toBe(a4); + expect(array[2]).toBe(a3); + expect(array[3]).toBe(a1); + }); }); \ No newline at end of file