[Perf] Optimize iteratees.orderBy

This commit is contained in:
Alexander Zinchuk 2021-12-04 13:43:49 +01:00
parent 412f26a6bf
commit 5563b0b4f4

View File

@ -1,6 +1,8 @@
type CollectionByKey<Member> = Record<number | string, Member>;
type OrderDirection = 'asc' | 'desc';
type OrderDirection =
'asc'
| 'desc';
interface OrderCallback<T> {
(member: T): any;
@ -51,55 +53,30 @@ export function omit<T, K extends keyof T>(object: T, keys: K[]) {
export function orderBy<T>(
collection: T[],
orderKey: (keyof T) | OrderCallback<T> | ((keyof T) | OrderCallback<T>)[],
orderRule: (keyof T) | OrderCallback<T> | ((keyof T) | OrderCallback<T>)[],
mode: OrderDirection | [OrderDirection, OrderDirection] = 'asc',
): T[] {
function compareValues(a: T, b: T, currentOrderRule: (keyof T) | OrderCallback<T>, isAsc: boolean) {
const aValue = (typeof currentOrderRule === 'function' ? currentOrderRule(a) : a[currentOrderRule]) || 0;
const bValue = (typeof currentOrderRule === 'function' ? currentOrderRule(b) : b[currentOrderRule]) || 0;
return isAsc ? aValue - bValue : bValue - aValue;
}
if (Array.isArray(orderRule)) {
const [mode1, mode2] = Array.isArray(mode) ? mode : [mode, mode];
const [orderRule1, orderRule2] = orderRule;
const isAsc1 = mode1 === 'asc';
const isAsc2 = mode2 === 'asc';
return collection.sort((a, b) => {
return compareValues(a, b, orderRule1, isAsc1) || compareValues(a, b, orderRule2, isAsc2);
});
}
const isAsc = mode === 'asc';
return collection.sort((a, b) => {
if (Array.isArray(orderKey)) {
const [mode1, mode2] = Array.isArray(mode) ? mode : [mode, mode];
const [orderKey1, orderKey2] = orderKey;
let aValue1;
let bValue1;
if (typeof orderKey1 === 'function') {
aValue1 = orderKey1(a) || 0;
bValue1 = orderKey1(b) || 0;
} else if (typeof orderKey1 === 'string') {
aValue1 = a[orderKey1] || 0;
bValue1 = b[orderKey1] || 0;
}
if (aValue1 !== bValue1) {
return mode1 === 'asc' ? aValue1 - bValue1 : bValue1 - aValue1;
} else {
let aValue2;
let bValue2;
if (typeof orderKey2 === 'function') {
aValue2 = orderKey2(a) || 0;
bValue2 = orderKey2(b) || 0;
} else if (typeof orderKey2 === 'string') {
aValue2 = a[orderKey2] || 0;
bValue2 = b[orderKey2] || 0;
}
return mode2 === 'asc' ? aValue2 - bValue2 : bValue2 - aValue2;
}
}
let aValue;
let bValue;
if (typeof orderKey === 'function') {
aValue = orderKey(a) || 0;
bValue = orderKey(b) || 0;
} else if (typeof orderKey === 'string') {
aValue = a[orderKey] || 0;
bValue = b[orderKey] || 0;
}
return mode === 'asc' ? aValue - bValue : bValue - aValue;
return compareValues(a, b, orderRule, isAsc);
});
}