Skip to content

Instantly share code, notes, and snippets.

@azanli
Last active June 24, 2019 18:24
Show Gist options
  • Select an option

  • Save azanli/ca24b53c018aea6f3c62ca0ae3004462 to your computer and use it in GitHub Desktop.

Select an option

Save azanli/ca24b53c018aea6f3c62ca0ae3004462 to your computer and use it in GitHub Desktop.
import idx from 'idx'
/*
* This code is copyright 2012 by Gavin Kistner, !@phrogz.net
* It is covered under the license viewable at http://phrogz.net/JS/_ReuseLicense.txt
* Schwartzian transform - https://en.wikipedia.org/wiki/Schwartzian_transform
*
* This is used mainly for additional sorting among equal values due to efficiency.
* Example: sortBy(data, o => [o.active, o.age, o.name]);
* i.e. sort by active, then amongst active sort by age, then amongst
* those of same age and active sort by name; likewise for inactive.
*/
export function sortByMultipleKeys(
array: Array<*> = [],
fun: () => {} = o => o,
order: Order = 'descend',
): Array<*> {
const result = [...array];
for (let i = result.length; i; ) {
const o = result[(i -= 1)];
// Group sort value(s) and item into an array
result[i] = [].concat(fun.call(o, o, i), o);
}
result.sort((a, b) => {
// Do comparison check on every sort value of both items
for (let i = 0; i < Math.max(a.length, b.length); i += 1) {
if (keyDoesNotExist(a, b, _ => _[i])) {
return compareNonExistingKey(a, b, _ => _[i]);
}
if (a[i] !== b[i]) {
const comparison = a[i] < b[i] ? -1 : 1;
return order === 'descend' ? comparison * -1 : comparison;
}
}
return 0;
});
for (let i = result.length; i; ) {
// Replace each index with only the original item
result[(i -= 1)] = result[i][result[i].length - 1];
}
return result;
}
export function keyDoesNotExist(a: mixed, b: mixed, fun: () => {}): number {
const ai = idx(a, fun);
if (ai === null || ai === undefined) {
return true;
}
const bi = idx(b, fun);
if (bi === null || bi === undefined) {
return true;
}
return false;
}
export function compareNonExistingKey(
a: mixed,
b: mixed,
fun: () => {},
): number {
const ai = idx(a, fun);
if (ai === null || ai === undefined) {
return 1;
}
const bi = idx(b, fun);
if (bi === null || bi === undefined) {
return -1;
}
return 0;
}
describe('sortByMultipleKeys', () => {
it('should sort an array based on multiple keys provided correctly in function argument', () => {
const relatableData = [
{ name: 'A3', active: true },
{ name: 'A5', active: false },
{ name: 'A2', active: true },
{ name: 'A1', active: true },
{ name: 'A4', active: false },
];
const multiplesResult = sortByMultipleKeys(
relatableData,
o => [o.active, o.name],
'ascend',
);
const snippetResult = [];
for (let i = 0; i < multiplesResult.length; i += 1) {
snippetResult.push({
name: multiplesResult[i].name,
active: multiplesResult[i].active,
});
}
expect(snippetResult).toEqual([
{ name: 'A4', active: false },
{ name: 'A5', active: false },
{ name: 'A1', active: true },
{ name: 'A2', active: true },
{ name: 'A3', active: true },
]);
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment