/
dropFirstBy.ts
77 lines (68 loc) · 3.29 KB
/
dropFirstBy.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
import { heapify, heapMaybeInsert } from "./_heap";
import type { OrderRule } from "./_purryOrderRules";
import { purryOrderRulesWithArgument } from "./_purryOrderRules";
import type { CompareFunction, NonEmptyArray } from "./_types";
/**
* Drop the first `n` items from `data` based on the provided ordering criteria. This allows you to avoid sorting the array before dropping the items. The complexity of this function is *O(Nlogn)* where `N` is the length of the array.
*
* For the opposite operation (to keep `n` elements) see `takeFirstBy`.
*
* @param data - The input array.
* @param n - The number of items to drop. If `n` is non-positive no items would be dropped and a *clone* of the input would be returned, if `n` is bigger then data.length no items would be returned.
* @param rules - A variadic array of order rules defining the sorting criteria. Each order rule is a projection function that extracts a comparable value from the data. Sorting is based on these extracted values using the native `<` and `>` operators. Earlier rules take precedence over later ones. Use the syntax `[projection, "desc"]` for descending order.
* @returns A subset of the input array.
* @signature
* R.dropFirstBy(data, n, ...rules);
* @example
* R.dropFirstBy(['aa', 'aaaa', 'a', 'aaa'], 2, x => x.length); // => ['aaa', 'aaaa']
* @dataFirst
* @category Array
*/
export function dropFirstBy<T>(
data: ReadonlyArray<T>,
n: number,
...rules: Readonly<NonEmptyArray<OrderRule<T>>>
): Array<T>;
/**
* Drop the first `n` items from `data` based on the provided ordering criteria. This allows you to avoid sorting the array before dropping the items. The complexity of this function is *O(Nlogn)* where `N` is the length of the array.
*
* For the opposite operation (to keep `n` elements) see `takeFirstBy`.
*
* @param n - The number of items to drop. If `n` is non-positive no items would be dropped and a *clone* of the input would be returned, if `n` is bigger then data.length no items would be returned.
* @param rules - A variadic array of order rules defining the sorting criteria. Each order rule is a projection function that extracts a comparable value from the data. Sorting is based on these extracted values using the native `<` and `>` operators. Earlier rules take precedence over later ones. Use the syntax `[projection, "desc"]` for descending order.
* @returns A subset of the input array.
* @signature
* R.dropFirstBy(n, ...rules)(data);
* @example
* R.pipe(['aa', 'aaaa', 'a', 'aaa'], R.dropFirstBy(2, x => x.length)); // => ['aaa', 'aaaa']
* @dataLast
* @category Array
*/
export function dropFirstBy<T>(
n: number,
...rules: Readonly<NonEmptyArray<OrderRule<T>>>
): (data: ReadonlyArray<T>) => Array<T>;
export function dropFirstBy(): unknown {
return purryOrderRulesWithArgument(dropFirstByImplementation, arguments);
}
function dropFirstByImplementation<T>(
data: ReadonlyArray<T>,
compareFn: CompareFunction<T>,
n: number,
): Array<T> {
if (n >= data.length) {
return [];
}
if (n <= 0) {
return data.slice();
}
const heap = data.slice(0, n);
heapify(heap, compareFn);
const out = [];
const rest = data.slice(n);
for (const item of rest) {
const previousHead = heapMaybeInsert(heap, compareFn, item);
out.push(previousHead ?? item);
}
return out;
}