/*! * array-sort * * Copyright (c) 2015-2017, Jon Schlinkert. * Released under the MIT License. */ 'use strict'; var defaultCompare = require('default-compare'); var typeOf = require('kind-of'); var get = require('get-value'); /** * Sort an array of objects by one or more properties. * * @param {Array} `arr` The Array to sort. * @param {String|Array|Function} `props` One or more object paths or comparison functions. * @param {Object} `opts` Pass `{ reverse: true }` to reverse the sort order. * @return {Array} Returns a sorted array. * @api public */ function arraySort(arr, props, opts) { if (arr == null) { return []; } if (!Array.isArray(arr)) { throw new TypeError('array-sort expects an array.'); } if (arguments.length === 1) { return arr.sort(); } var args = flatten([].slice.call(arguments, 1)); // if the last argument appears to be a plain object, // it's not a valid `compare` arg, so it must be options. if (typeOf(args[args.length - 1]) === 'object') { opts = args.pop(); } return arr.sort(sortBy(args, opts)); } /** * Iterate over each comparison property or function until `1` or `-1` * is returned. * * @param {String|Array|Function} `props` One or more object paths or comparison functions. * @param {Object} `opts` Pass `{ reverse: true }` to reverse the sort order. * @return {Array} */ function sortBy(props, opts) { opts = opts || {}; return function compareFn(a, b) { var len = props.length, i = -1; var result; while (++i < len) { result = compare(props[i], a, b); if (result !== 0) { break; } } if (opts.reverse === true) { return result * -1; } return result; }; } /** * Compare `a` to `b`. If an object `prop` is passed, then * `a[prop]` is compared to `b[prop]` */ function compare(prop, a, b) { if (typeof prop === 'function') { // expose `compare` to custom function return prop(a, b, compare.bind(null, null)); } // compare object values if (prop && typeof a === 'object' && typeof b === 'object') { return compare(null, get(a, prop), get(b, prop)); } return defaultCompare(a, b); } /** * Flatten the given array. */ function flatten(arr) { return [].concat.apply([], arr); } /** * Expose `arraySort` */ module.exports = arraySort;