Comparing version 2.1.3 to 2.2.0
@@ -0,1 +1,8 @@ | ||
declare type IOrder = 1 | -1; | ||
export interface IComparer { | ||
(a: any, b: any, order: IOrder): number; | ||
} | ||
export interface ISortInstanceOptions { | ||
comparer?: IComparer; | ||
} | ||
export interface ISortByFunction<T> { | ||
@@ -5,13 +12,10 @@ (prop: T): any; | ||
export declare type ISortBy<T> = keyof T | ISortByFunction<T> | (keyof T | ISortByFunction<T>)[]; | ||
export interface ISortComparer { | ||
comparer?(a: any, b: any, order: 1 | -1): number; | ||
} | ||
export interface ISortByAscSorter<T> extends ISortComparer { | ||
export interface ISortByAscSorter<T> extends ISortInstanceOptions { | ||
asc: boolean | ISortBy<T>; | ||
} | ||
export interface ISortByDescSorter<T> extends ISortComparer { | ||
export interface ISortByDescSorter<T> extends ISortInstanceOptions { | ||
desc: boolean | ISortBy<T>; | ||
} | ||
export declare type ISortByObjectSorter<T> = ISortByAscSorter<T> | ISortByDescSorter<T>; | ||
declare function createSortInstance(opts: ISortComparer): <T>(ctx: T[]) => { | ||
declare function createSortInstance(opts: ISortInstanceOptions): <T>(ctx: T[]) => { | ||
/** | ||
@@ -18,0 +22,0 @@ * Sort array in ascending order. Mutates provided array by sorting it. |
@@ -0,5 +1,7 @@ | ||
// >>> INTERFACES <<< | ||
// >>> HELPERS <<< | ||
var orderHandler = function (comparer) { return function (a, b, order) { return comparer(a, b, order) * order; }; }; | ||
var throwInvalidConfigError = function (context) { | ||
throw Error("Invalid sort config: " + context); | ||
var castComparer = function (comparer) { return function (a, b, order) { return comparer(a, b, order) * order; }; }; | ||
var throwInvalidConfigErrorIfTrue = function (condition, context) { | ||
if (condition) | ||
throw Error("Invalid sort config: " + context); | ||
}; | ||
@@ -9,10 +11,7 @@ var unpackObjectSorter = function (sortByObj) { | ||
var order = asc ? 1 : -1; | ||
var sortBy = asc || desc; | ||
if (asc && desc) { | ||
throw throwInvalidConfigError('Ambiguous object with `asc` and `desc` config properties'); | ||
} | ||
if (!sortBy) { | ||
throwInvalidConfigError('Expected `asc` or `desc` property'); | ||
} | ||
var comparer = sortByObj.comparer && orderHandler(sortByObj.comparer); | ||
var sortBy = (asc || desc); | ||
// Validate object config | ||
throwInvalidConfigErrorIfTrue(!sortBy, 'Expected `asc` or `desc` property'); | ||
throwInvalidConfigErrorIfTrue(asc && desc, 'Ambiguous object with `asc` and `desc` config properties'); | ||
var comparer = sortByObj.comparer && castComparer(sortByObj.comparer); | ||
return { order: order, sortBy: sortBy, comparer: comparer }; | ||
@@ -22,3 +21,3 @@ }; | ||
var multiPropertySorterProvider = function (defaultComparer) { | ||
return function multiPropertySorter(sortBy, sortByArray, depth, order, comparer, a, b) { | ||
return function multiPropertySorter(sortBy, sortByArr, depth, order, comparer, a, b) { | ||
var valA; | ||
@@ -36,8 +35,8 @@ var valB; | ||
var objectSorterConfig = unpackObjectSorter(sortBy); | ||
return multiPropertySorter(objectSorterConfig.sortBy, sortByArray, depth, objectSorterConfig.order, objectSorterConfig.comparer || defaultComparer, a, b); | ||
return multiPropertySorter(objectSorterConfig.sortBy, sortByArr, depth, objectSorterConfig.order, objectSorterConfig.comparer || defaultComparer, a, b); | ||
} | ||
var equality = comparer(valA, valB, order); | ||
if (sortByArray.length > depth && | ||
(equality === 0 || (valA == null && valB == null))) { | ||
return multiPropertySorter(sortByArray[depth], sortByArray, depth + 1, order, comparer, a, b); | ||
if ((equality === 0 || (valA == null && valB == null)) && | ||
sortByArr.length > depth) { | ||
return multiPropertySorter(sortByArr[depth], sortByArr, depth + 1, order, comparer, a, b); | ||
} | ||
@@ -47,2 +46,25 @@ return equality; | ||
}; | ||
function getSortStrategy(sortBy, comparer, order) { | ||
// Flat array sorter | ||
if (sortBy === undefined || sortBy === true) { | ||
return function (a, b) { return comparer(a, b, order); }; | ||
} | ||
// Sort list of objects by single object key | ||
if (typeof sortBy === 'string') { | ||
throwInvalidConfigErrorIfTrue(sortBy.includes('.'), 'String syntax not allowed for nested properties.'); | ||
return function (a, b) { return comparer(a[sortBy], b[sortBy], order); }; | ||
} | ||
// Sort list of objects by single function sorter | ||
if (typeof sortBy === 'function') { | ||
return function (a, b) { return comparer(sortBy(a), sortBy(b), order); }; | ||
} | ||
// Sort by multiple properties | ||
if (Array.isArray(sortBy)) { | ||
var multiPropSorter_1 = multiPropertySorterProvider(comparer); | ||
return function (a, b) { return multiPropSorter_1(sortBy[0], sortBy, 1, order, comparer, a, b); }; | ||
} | ||
// Unpack object config to get actual sorter strategy | ||
var objectSorterConfig = unpackObjectSorter(sortBy); | ||
return getSortStrategy(objectSorterConfig.sortBy, objectSorterConfig.comparer || comparer, objectSorterConfig.order); | ||
} | ||
var sort = function (order, ctx, sortBy, comparer) { | ||
@@ -53,31 +75,11 @@ var _a; | ||
} | ||
// Unwrap sortBy if array with only 1 value | ||
// Unwrap sortBy if array with only 1 value to get faster sort strategy | ||
if (Array.isArray(sortBy) && sortBy.length < 2) { | ||
_a = sortBy, sortBy = _a[0]; | ||
} | ||
var sorter; | ||
if (sortBy === undefined || sortBy === true) { | ||
sorter = function (a, b) { return comparer(a, b, order); }; | ||
} | ||
else if (typeof sortBy === 'string') { | ||
if (sortBy.includes('.')) { | ||
throw throwInvalidConfigError('String syntax not allowed for nested properties.'); | ||
} | ||
sorter = function (a, b) { return comparer(a[sortBy], b[sortBy], order); }; | ||
} | ||
else if (typeof sortBy === 'function') { | ||
sorter = function (a, b) { return comparer(sortBy(a), sortBy(b), order); }; | ||
} | ||
else if (Array.isArray(sortBy)) { | ||
sorter = multiPropertySorterProvider(comparer) | ||
.bind(undefined, sortBy[0], sortBy, 1, order, comparer); | ||
} | ||
else { | ||
var objectSorterConfig = unpackObjectSorter(sortBy); | ||
return sort(objectSorterConfig.order, ctx, objectSorterConfig.sortBy, objectSorterConfig.comparer || comparer); | ||
} | ||
return ctx.sort(sorter); | ||
return ctx.sort(getSortStrategy(sortBy, comparer, order)); | ||
}; | ||
// >>> Public <<< | ||
function createSortInstance(opts) { | ||
var comparer = orderHandler(opts.comparer); | ||
var comparer = castComparer(opts.comparer); | ||
return function (ctx) { | ||
@@ -84,0 +86,0 @@ return { |
@@ -7,6 +7,8 @@ (function (global, factory) { | ||
// >>> INTERFACES <<< | ||
// >>> HELPERS <<< | ||
var orderHandler = function (comparer) { return function (a, b, order) { return comparer(a, b, order) * order; }; }; | ||
var throwInvalidConfigError = function (context) { | ||
throw Error("Invalid sort config: " + context); | ||
var castComparer = function (comparer) { return function (a, b, order) { return comparer(a, b, order) * order; }; }; | ||
var throwInvalidConfigErrorIfTrue = function (condition, context) { | ||
if (condition) | ||
throw Error("Invalid sort config: " + context); | ||
}; | ||
@@ -16,10 +18,7 @@ var unpackObjectSorter = function (sortByObj) { | ||
var order = asc ? 1 : -1; | ||
var sortBy = asc || desc; | ||
if (asc && desc) { | ||
throw throwInvalidConfigError('Ambiguous object with `asc` and `desc` config properties'); | ||
} | ||
if (!sortBy) { | ||
throwInvalidConfigError('Expected `asc` or `desc` property'); | ||
} | ||
var comparer = sortByObj.comparer && orderHandler(sortByObj.comparer); | ||
var sortBy = (asc || desc); | ||
// Validate object config | ||
throwInvalidConfigErrorIfTrue(!sortBy, 'Expected `asc` or `desc` property'); | ||
throwInvalidConfigErrorIfTrue(asc && desc, 'Ambiguous object with `asc` and `desc` config properties'); | ||
var comparer = sortByObj.comparer && castComparer(sortByObj.comparer); | ||
return { order: order, sortBy: sortBy, comparer: comparer }; | ||
@@ -29,3 +28,3 @@ }; | ||
var multiPropertySorterProvider = function (defaultComparer) { | ||
return function multiPropertySorter(sortBy, sortByArray, depth, order, comparer, a, b) { | ||
return function multiPropertySorter(sortBy, sortByArr, depth, order, comparer, a, b) { | ||
var valA; | ||
@@ -43,8 +42,8 @@ var valB; | ||
var objectSorterConfig = unpackObjectSorter(sortBy); | ||
return multiPropertySorter(objectSorterConfig.sortBy, sortByArray, depth, objectSorterConfig.order, objectSorterConfig.comparer || defaultComparer, a, b); | ||
return multiPropertySorter(objectSorterConfig.sortBy, sortByArr, depth, objectSorterConfig.order, objectSorterConfig.comparer || defaultComparer, a, b); | ||
} | ||
var equality = comparer(valA, valB, order); | ||
if (sortByArray.length > depth && | ||
(equality === 0 || (valA == null && valB == null))) { | ||
return multiPropertySorter(sortByArray[depth], sortByArray, depth + 1, order, comparer, a, b); | ||
if ((equality === 0 || (valA == null && valB == null)) && | ||
sortByArr.length > depth) { | ||
return multiPropertySorter(sortByArr[depth], sortByArr, depth + 1, order, comparer, a, b); | ||
} | ||
@@ -54,2 +53,25 @@ return equality; | ||
}; | ||
function getSortStrategy(sortBy, comparer, order) { | ||
// Flat array sorter | ||
if (sortBy === undefined || sortBy === true) { | ||
return function (a, b) { return comparer(a, b, order); }; | ||
} | ||
// Sort list of objects by single object key | ||
if (typeof sortBy === 'string') { | ||
throwInvalidConfigErrorIfTrue(sortBy.includes('.'), 'String syntax not allowed for nested properties.'); | ||
return function (a, b) { return comparer(a[sortBy], b[sortBy], order); }; | ||
} | ||
// Sort list of objects by single function sorter | ||
if (typeof sortBy === 'function') { | ||
return function (a, b) { return comparer(sortBy(a), sortBy(b), order); }; | ||
} | ||
// Sort by multiple properties | ||
if (Array.isArray(sortBy)) { | ||
var multiPropSorter_1 = multiPropertySorterProvider(comparer); | ||
return function (a, b) { return multiPropSorter_1(sortBy[0], sortBy, 1, order, comparer, a, b); }; | ||
} | ||
// Unpack object config to get actual sorter strategy | ||
var objectSorterConfig = unpackObjectSorter(sortBy); | ||
return getSortStrategy(objectSorterConfig.sortBy, objectSorterConfig.comparer || comparer, objectSorterConfig.order); | ||
} | ||
var sort = function (order, ctx, sortBy, comparer) { | ||
@@ -60,31 +82,11 @@ var _a; | ||
} | ||
// Unwrap sortBy if array with only 1 value | ||
// Unwrap sortBy if array with only 1 value to get faster sort strategy | ||
if (Array.isArray(sortBy) && sortBy.length < 2) { | ||
_a = sortBy, sortBy = _a[0]; | ||
} | ||
var sorter; | ||
if (sortBy === undefined || sortBy === true) { | ||
sorter = function (a, b) { return comparer(a, b, order); }; | ||
} | ||
else if (typeof sortBy === 'string') { | ||
if (sortBy.includes('.')) { | ||
throw throwInvalidConfigError('String syntax not allowed for nested properties.'); | ||
} | ||
sorter = function (a, b) { return comparer(a[sortBy], b[sortBy], order); }; | ||
} | ||
else if (typeof sortBy === 'function') { | ||
sorter = function (a, b) { return comparer(sortBy(a), sortBy(b), order); }; | ||
} | ||
else if (Array.isArray(sortBy)) { | ||
sorter = multiPropertySorterProvider(comparer) | ||
.bind(undefined, sortBy[0], sortBy, 1, order, comparer); | ||
} | ||
else { | ||
var objectSorterConfig = unpackObjectSorter(sortBy); | ||
return sort(objectSorterConfig.order, ctx, objectSorterConfig.sortBy, objectSorterConfig.comparer || comparer); | ||
} | ||
return ctx.sort(sorter); | ||
return ctx.sort(getSortStrategy(sortBy, comparer, order)); | ||
}; | ||
// >>> Public <<< | ||
function createSortInstance(opts) { | ||
var comparer = orderHandler(opts.comparer); | ||
var comparer = castComparer(opts.comparer); | ||
return function (ctx) { | ||
@@ -91,0 +93,0 @@ return { |
@@ -1,1 +0,1 @@ | ||
!function(r,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):(r=r||self)["fast-sort"]=n()}(this,function(){"use strict";function u(t){return function(r,n,e){return t(r,n,e)*e}}function f(r){throw Error("Invalid sort config: "+r)}function l(r){var n=r||{},e=n.asc,t=n.desc,o=e?1:-1,i=e||t;if(e&&t)throw f("Ambiguous object with `asc` and `desc` config properties");return i||f("Expected `asc` or `desc` property"),{order:o,sortBy:i,comparer:r.comparer&&u(r.comparer)}}var c=function(e,r,t,o){var n,p;if(!Array.isArray(r))return r;if(Array.isArray(t)&&t.length<2&&(t=t[0]),void 0===t||!0===t)n=function(r,n){return o(r,n,e)};else if("string"==typeof t){if(t.includes("."))throw f("String syntax not allowed for nested properties.");n=function(r,n){return o(r[t],n[t],e)}}else if("function"==typeof t)n=function(r,n){return o(t(r),t(n),e)};else{if(!Array.isArray(t)){var i=l(t);return c(i.order,r,i.sortBy,i.comparer||o)}p=o,n=function r(n,e,t,o,i,u,f){var c,s;if("string"==typeof n)c=u[n],s=f[n];else{if("function"!=typeof n){var a=l(n);return r(a.sortBy,e,t,a.order,a.comparer||p,u,f)}c=n(u),s=n(f)}var d=i(c,s,o);return e.length>t&&(0===d||null==c&&null==s)?r(e[t],e,t+1,o,i,u,f):d}.bind(void 0,t[0],t,1,e,o)}return r.sort(n)};function r(r){var e=u(r.comparer);return function(n){return{asc:function(r){return c(1,n,r,e)},desc:function(r){return c(-1,n,r,e)},by:function(r){return c(1,n,r,e)}}}}var n=r({comparer:function(r,n,e){return null==r?e:null==n?-e:r<n?-1:r===n?0:1}});return n.createNewInstance=r,n}); | ||
!function(r,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):(r=r||self)["fast-sort"]=n()}(this,function(){"use strict";function i(e){return function(r,n,t){return e(r,n,t)*t}}var c=function(r,n){if(r)throw Error("Invalid sort config: "+n)},y=function(r){var n=r||{},t=n.asc,e=n.desc,o=t?1:-1,u=t||e;return c(!u,"Expected `asc` or `desc` property"),c(t&&e,"Ambiguous object with `asc` and `desc` config properties"),{order:o,sortBy:u,comparer:r.comparer&&i(r.comparer)}},f=function(d){return function r(n,t,e,o,u,i,c){var f,a;if("string"==typeof n)f=i[n],a=c[n];else{if("function"!=typeof n){var s=y(n);return r(s.sortBy,t,e,s.order,s.comparer||d,i,c)}f=n(i),a=n(c)}var p=u(f,a,o);return(0===p||null==f&&null==a)&&t.length>e?r(t[e],t,e+1,o,u,i,c):p}};function e(r,n,t,e){return Array.isArray(n)?(Array.isArray(t)&&t.length<2&&(t=t[0]),n.sort(function r(t,e,o){if(void 0===t||!0===t)return function(r,n){return e(r,n,o)};if("string"==typeof t)return c(t.includes("."),"String syntax not allowed for nested properties."),function(r,n){return e(r[t],n[t],o)};if("function"==typeof t)return function(r,n){return e(t(r),t(n),o)};if(Array.isArray(t)){var u=f(e);return function(r,n){return u(t[0],t,1,o,e,r,n)}}var n=y(t);return r(n.sortBy,n.comparer||e,n.order)}(t,e,r))):n}function r(r){var t=i(r.comparer);return function(n){return{asc:function(r){return e(1,n,r,t)},desc:function(r){return e(-1,n,r,t)},by:function(r){return e(1,n,r,t)}}}}var n=r({comparer:function(r,n,t){return null==r?t:null==n?-t:r<n?-1:r===n?0:1}});return n.createNewInstance=r,n}); |
{ | ||
"name": "fast-sort", | ||
"version": "2.1.3", | ||
"version": "2.2.0", | ||
"description": "Fast and powerful array sorting. Sort by any property in any direction with easy to read syntax.", | ||
@@ -45,7 +45,7 @@ "main": "dist/sort.js", | ||
"chai": "^4.2.0", | ||
"eslint": "^6.8.0", | ||
"eslint": "^7.0.0", | ||
"eslint-config-airbnb-base": "^14.1.0", | ||
"eslint-plugin-import": "^2.20.2", | ||
"mocha": "^7.1.2", | ||
"rollup": "^2.8.0", | ||
"rollup": "^2.8.2", | ||
"rollup-plugin-typescript2": "^0.27.0", | ||
@@ -52,0 +52,0 @@ "rollup-plugin-uglify": "^6.0.4", |
@@ -59,3 +59,3 @@ # fast-sort | ||
* `asc` / `desc` sorters. In below examples we will use `asc` sorter but keep in mind that both `asc` and `desc` sorters have exactly the same API so all the examples below can be applied for `desc` sorter. | ||
* `asc` / `desc` sorters. Both asc and desc sorters have exactly the same API. | ||
@@ -109,6 +109,6 @@ ```javascript | ||
// Sort users by city using custom comparer | ||
sort(users).by([ | ||
sort(users).by({ | ||
asc: u => u.address.city, | ||
comparer: (a, b) => a.localeCompare(b), | ||
]); | ||
}); | ||
@@ -130,3 +130,3 @@ // Sort users ascending by age using default comparer and then by lastName using language sensitive comparer | ||
By default `fast-sort` is not doing language sensitive sorting of strings. | ||
e.g `image-11.jpg` will be sorted before `image-2.jpg` (in ascending sorting). | ||
e.g `'image-11.jpg'` will be sorted before `'image-2.jpg'` (in ascending sorting). | ||
We can provide custom [Intl.Collator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Collator) comparer to fast-sort for language sensitive sorting of strings. | ||
@@ -207,4 +207,5 @@ Keep in mind that natural sort is slower then default sorting so recommendation is to use it | ||
console.log(arr); // => [1, 2, 4] | ||
console.log(sortedArr === arr), // => true | ||
// To prevent that we can use ES6 destructor (or ES5 equivalents) | ||
// TIP: to prevent mutating of input array you can clone it before passing to sort as | ||
const arr = [1, 4, 2]; | ||
@@ -214,4 +215,5 @@ const sortedArr = sort([...arr]).asc(); | ||
console.log(sortedArr); // => [1, 2, 4] | ||
console.log(sortedArr === arr), // => false | ||
// As stated in highlights fast-sort sorts null and undefined values to the | ||
// As stated in highlights by default fast-sort sorts null and undefined values to the | ||
// bottom no matter if sorting is in asc or decs order. | ||
@@ -218,0 +220,0 @@ const addresses = [{ city: 'Split' }, { city: undefined }, { city: 'Zagreb'}]; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
30813
381
301