index.js 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. /*!
  2. * array-sort <https://github.com/jonschlinkert/array-sort>
  3. *
  4. * Copyright (c) 2015-2017, Jon Schlinkert.
  5. * Released under the MIT License.
  6. */
  7. 'use strict';
  8. var defaultCompare = require('default-compare');
  9. var typeOf = require('kind-of');
  10. var get = require('get-value');
  11. /**
  12. * Sort an array of objects by one or more properties.
  13. *
  14. * @param {Array} `arr` The Array to sort.
  15. * @param {String|Array|Function} `props` One or more object paths or comparison functions.
  16. * @param {Object} `opts` Pass `{ reverse: true }` to reverse the sort order.
  17. * @return {Array} Returns a sorted array.
  18. * @api public
  19. */
  20. function arraySort(arr, props, opts) {
  21. if (arr == null) {
  22. return [];
  23. }
  24. if (!Array.isArray(arr)) {
  25. throw new TypeError('array-sort expects an array.');
  26. }
  27. if (arguments.length === 1) {
  28. return arr.sort();
  29. }
  30. var args = flatten([].slice.call(arguments, 1));
  31. // if the last argument appears to be a plain object,
  32. // it's not a valid `compare` arg, so it must be options.
  33. if (typeOf(args[args.length - 1]) === 'object') {
  34. opts = args.pop();
  35. }
  36. return arr.sort(sortBy(args, opts));
  37. }
  38. /**
  39. * Iterate over each comparison property or function until `1` or `-1`
  40. * is returned.
  41. *
  42. * @param {String|Array|Function} `props` One or more object paths or comparison functions.
  43. * @param {Object} `opts` Pass `{ reverse: true }` to reverse the sort order.
  44. * @return {Array}
  45. */
  46. function sortBy(props, opts) {
  47. opts = opts || {};
  48. return function compareFn(a, b) {
  49. var len = props.length, i = -1;
  50. var result;
  51. while (++i < len) {
  52. result = compare(props[i], a, b);
  53. if (result !== 0) {
  54. break;
  55. }
  56. }
  57. if (opts.reverse === true) {
  58. return result * -1;
  59. }
  60. return result;
  61. };
  62. }
  63. /**
  64. * Compare `a` to `b`. If an object `prop` is passed, then
  65. * `a[prop]` is compared to `b[prop]`
  66. */
  67. function compare(prop, a, b) {
  68. if (typeof prop === 'function') {
  69. // expose `compare` to custom function
  70. return prop(a, b, compare.bind(null, null));
  71. }
  72. // compare object values
  73. if (prop && typeof a === 'object' && typeof b === 'object') {
  74. return compare(null, get(a, prop), get(b, prop));
  75. }
  76. return defaultCompare(a, b);
  77. }
  78. /**
  79. * Flatten the given array.
  80. */
  81. function flatten(arr) {
  82. return [].concat.apply([], arr);
  83. }
  84. /**
  85. * Expose `arraySort`
  86. */
  87. module.exports = arraySort;