-
Notifications
You must be signed in to change notification settings - Fork 14
/
Copy pathcreateComparatorFactory.ts
100 lines (89 loc) · 2.86 KB
/
createComparatorFactory.ts
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
import ComparatorFactory from "./ComparatorFactory";
import Comparator from "./Comparator";
function compare<T>(comparison: (a: T, b: T) => number): Comparator<T> {
return Object.assign(comparison, {
reversed(): Comparator<T> {
return compare(
(a: T, b: T) => comparison(a, b) * -1
);
},
then(nextComparison: (a: T, b: T) => number): Comparator<T> {
return compare(
(a: T, b: T) => {
const result = comparison(a, b);
return result !== 0
? result
: nextComparison(a, b);
}
);
},
thenDescending(nextComparison: (a: T, b: T) => number): Comparator<T> {
return this.then(
compare(nextComparison)
.reversed()
);
},
thenBy(keyOrSelector: any): Comparator<T> {
const selector = asSelector<T>(keyOrSelector);
return this.then(
(a: T, b: T) => naturalCompare(selector(a), selector(b))
);
},
thenByDescending(keyOrSelector: any): Comparator<T> {
const selector = asSelector<T>(keyOrSelector);
return this.then(
compare(
(a: T, b: T) => naturalCompare(selector(a), selector(b))
).reversed()
);
}
});
}
function compareBy<T>(keyOrSelector: any): Comparator<T> {
const selector = asSelector<T>(keyOrSelector);
return compare<T>(
(a: T, b: T) => naturalCompare(selector(a), selector(b))
);
}
function compareByDescending<T>(keyOrSelector: any): Comparator<T> {
const selector = asSelector<T>(keyOrSelector);
return compare<T>(
(a: T, b: T) => naturalCompare(selector(b), selector(a))
);
}
function asSelector<T>(keyOrSelector: (item: T) => any | string): (item: T) => any {
return typeof keyOrSelector === "function"
? keyOrSelector
: (item: T) => (item as any)[keyOrSelector as string];
}
function naturalCompare<T>(a: T, b: T): number {
return a < b ? -1 : a > b ? 1 : 0;
}
function naturalOrder<T>(): Comparator<T> {
return compare(naturalCompare);
}
function reverseOrder<T>(): Comparator<T> {
return compare<T>(naturalCompare).reversed();
}
function nullsLast<T>(): Comparator<T> {
return compare<T>(
(a: T, b: T) => a === null ? 1 : b === null ? -1 : 0
);
}
function nullsFirst<T>(): Comparator<T> {
return compare<T>(
(a: T, b: T) => a === null ? -1 : b === null ? 1 : 0
);
}
function createComparatorFactory<T>(): ComparatorFactory<T> {
return {
compare,
compareBy,
compareByDescending,
naturalOrder,
reverseOrder,
nullsFirst,
nullsLast
};
}
export default createComparatorFactory;