Last active
July 19, 2017 13:01
-
-
Save malko/06745377a82d3cbda2b9 to your computer and use it in GitHub Desktop.
make a multiple fields comparator for sort functions
This file contains 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
/** | |
* return a comparator to use in Array.sort method context. | |
* take a list of properties (array or string delimited by pipe or comma) which you want to use for sort | |
* @param {(string|string[])) fields list of properties names (array or string delimited by pipe or comma) which you want to use for sort | |
* each field name may be prefixed by an < or > to sort on ascending or descending order | |
* you can use n< or n> as prefix for a natural order sorting | |
* @returns {function(object, object)} | |
*/ | |
function propertyComparator(compareConfig) { | |
if (typeof compareConfig === 'string') { | |
compareConfig = compareConfig.split(/[|,]/); | |
} | |
let propertyName = compareConfig.shift(); | |
let isDescending = false; | |
let isNatural = false; | |
const next = compareConfig.length ? propertyComparator(compareConfig) : () => 0; | |
const [comparatorConfig, naturalFlag, orderSymbol] = propertyName.match(/^(n?)(<|>)/) || ['', '', '']; | |
if (comparatorConfig) { | |
naturalFlag === 'n' && (isNatural = true); | |
orderSymbol === '>' && (isDescending = true); | |
propertyName = propertyName.slice(comparatorConfig.length); | |
} | |
const comparator = propertyComparator[isNatural ? 'createNaturalComparator' : 'createBasicComparator'](propertyName); | |
if (isDescending) { | |
return (a, b) => comparator(b, a) || next(a, b); | |
} | |
return (a, b) => comparator(a, b) || next(a, b); | |
} | |
/** | |
* create a basic comparator between two objects based on given property name | |
* @param {string} propertyName name of the property used for comparison | |
* @returns {function(object, object)} | |
*/ | |
propertyComparator.prototype.createBasicComparator = (propertyName) => { | |
return (a, b) => { | |
if (a[propertyName] > b[propertyName]) { | |
return 1; | |
} | |
return a[propertyName] < b[propertyName] ? -1 : 0; | |
}; | |
}; | |
/** | |
* create a natural comparator between two objects based on given property name | |
* @param {string} propertyName name of the property used for comparison | |
* @returns {function(object, object)} | |
*/ | |
propertyComparator.prototype.createNaturalComparator = (fieldName) => { | |
if (String.prototype.localeCompare) { | |
return (a, b) => a[fieldName].localeCompare(b[fieldName], undefined, { numeric: true }); | |
} else { | |
return propertyComparator.createBasicComparator(fieldName); | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment