Last active
June 24, 2019 18:24
-
-
Save azanli/ca24b53c018aea6f3c62ca0ae3004462 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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