-
Notifications
You must be signed in to change notification settings - Fork 0
/
ComparerBuilder.ts
65 lines (61 loc) · 2.25 KB
/
ComparerBuilder.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
import { Comparer } from './Comparer'
export interface BuildableComparer<T> {
build(): Comparer<T>
}
interface BaseComparerBuilder<T> extends BuildableComparer<T> {
sortKey<TComparable>(selector: (x: T) => TComparable): ThenComparerBuilder<T>
sortKeyDescending<TComparable>(selector: (x: T) => TComparable): ThenComparerBuilder<T>
}
export interface ThenComparerBuilder<T> extends BuildableComparer<T> {
thenKey<TComparable>(selector: (x: T) => TComparable): ThenComparerBuilder<T>
thenKeyDescending<TComparable>(selector: (x: T) => TComparable): ThenComparerBuilder<T>
}
export class ComparerBuilder<T> implements BaseComparerBuilder<T>, ThenComparerBuilder<T> {
static create<T>(): ComparerBuilder<T> {
return new ComparerBuilder<T>()
}
thenKey<TComparable>(selector: (x: T) => TComparable): ThenComparerBuilder<T> {
return this.sortKey(selector)
}
thenKeyDescending<TComparable>(selector: (x: T) => TComparable): ThenComparerBuilder<T> {
return this.sortKeyDescending(selector)
}
private comparers: Comparer<T>[]
constructor(comparers: Array<Comparer<T>> | undefined = undefined) {
this.comparers = comparers || []
}
sortKey<TComparable>(selector: (x: T) => TComparable): ThenComparerBuilder<T> {
const c = this.createComparer(selector, (a, b) => (a < b ? -1 : a > b ? 1 : 0))
const newComparers = [...this.comparers]
newComparers.push(c)
return new ComparerBuilder<T>(newComparers)
}
sortKeyDescending<TComparable>(selector: (x: T) => TComparable): ThenComparerBuilder<T> {
const c = this.createComparer(selector, (a, b) => (a < b ? 1 : a > b ? -1 : 0))
const newComparers = [...this.comparers]
newComparers.push(c)
return new ComparerBuilder<T>(newComparers)
}
private createComparer<TComparable>(
selector: (x: T) => TComparable,
comparer: Comparer<TComparable>
): Comparer<T> {
return (a, b) => {
const cmpA = selector(a)
const cmpB = selector(b)
return comparer(cmpA, cmpB)
}
}
build(): Comparer<T> {
return (a, b) => {
for (let i = 0; i < this.comparers.length; i++) {
const comparer = this.comparers[i]
const comparison = comparer(a, b)
if (comparison !== 0) {
return comparison
}
}
return 0
}
}
}