API Docs for: 3.18.1
Show:

File: arraysort/js/arraysort.js

  1. /*jshint expr:true, onevar:false */
  2.  
  3. /**
  4. Provides comparator functions useful for sorting arrays.
  5.  
  6. @module arraysort
  7. **/
  8.  
  9. var LANG = Y.Lang,
  10. ISVALUE = LANG.isValue,
  11. ISSTRING = LANG.isString;
  12.  
  13. /**
  14. Provides comparator functions useful for sorting arrays.
  15.  
  16. @class ArraySort
  17. @static
  18. **/
  19.  
  20. var ArraySort = Y.ArraySort = {
  21. // -- Public Methods -------------------------------------------------------
  22.  
  23. /**
  24. Comparator function for simple case-insensitive sorting of an array of
  25. strings.
  26.  
  27. @method compare
  28. @param a {Object} First sort argument.
  29. @param b {Object} Second sort argument.
  30. @param desc {Boolean} `true` if sort direction is descending, `false` if
  31. sort direction is ascending.
  32. @return {Boolean} -1 when a < b. 0 when a == b. 1 when a > b.
  33. @static
  34. */
  35. compare: function(a, b, desc) {
  36. if(!ISVALUE(a)) {
  37. if(!ISVALUE(b)) {
  38. return 0;
  39. }
  40. else {
  41. return 1;
  42. }
  43. }
  44. else if(!ISVALUE(b)) {
  45. return -1;
  46. }
  47.  
  48. if(ISSTRING(a)) {
  49. a = a.toLowerCase();
  50. }
  51. if(ISSTRING(b)) {
  52. b = b.toLowerCase();
  53. }
  54. if(a < b) {
  55. return (desc) ? 1 : -1;
  56. }
  57. else if (a > b) {
  58. return (desc) ? -1 : 1;
  59. }
  60. else {
  61. return 0;
  62. }
  63. },
  64.  
  65. /**
  66. Performs a natural-order comparison of two strings or numbers (or a string
  67. and a number). This ensures that a value like 'foo2' will be sorted before
  68. 'foo10', whereas a standard ASCII sort would sort 'foo10' first.
  69.  
  70. @example
  71.  
  72. var items = ['item10', 'item2', 'item1', 10, '1', 2];
  73.  
  74. items.sort(Y.ArraySort.naturalCompare);
  75. console.log(items); // => ['1', 2, 10, 'item1', 'item2', 'item10']
  76.  
  77. @method naturalCompare
  78. @param {Number|String} a First value to compare.
  79. @param {Number|String} b Second value to compare.
  80. @param {Object} [options] Options.
  81. @param {Boolean} [options.caseSensitive=false] If `true`, a
  82. case-sensitive comparison will be performed. By default the
  83. comparison is case-insensitive.
  84. @param {Boolean} [options.descending=false] If `true`, the sort order
  85. will be reversed so that larger values are sorted before smaller
  86. values.
  87. @return {Number} `0` if the two items are equal, a negative number if _a_
  88. should be sorted before _b_, or a positive number if _b_ should be
  89. sorted before _a_.
  90. @static
  91. @since 3.11.0
  92. **/
  93. naturalCompare: function (a, b, options) {
  94. // Coerce `a` and `b` to strings.
  95. a += '';
  96. b += '';
  97.  
  98. // Convert `a` and `b` to lowercase unless `options.caseSensitive` is
  99. // truthy.
  100. if (!options || !options.caseSensitive) {
  101. a = a.toLowerCase();
  102. b = b.toLowerCase();
  103. }
  104.  
  105. // Split `a` and `b` into alpha parts and numeric parts.
  106. var aParts = ArraySort._splitAlphaNum(a),
  107. bParts = ArraySort._splitAlphaNum(b),
  108. length = Math.min(aParts.length, bParts.length),
  109. result = 0,
  110.  
  111. aPart,
  112. bPart,
  113. i;
  114.  
  115. // Compare each part of `a` with each part of `b`.
  116. for (i = 0; i < length; i++) {
  117. aPart = aParts[i];
  118. bPart = bParts[i];
  119.  
  120. // If the two parts aren't equal, compare them and stop iterating.
  121. if (aPart !== bPart) {
  122. // First, try comparing them as numbers.
  123. result = aPart - bPart;
  124.  
  125. // If that didn't work, compare them as strings. This falsiness
  126. // check works because `result` can't be 0 (we checked for
  127. // equality above) and NaN is falsy.
  128. if (!result) {
  129. result = aPart > bPart ? 1 : -1;
  130. }
  131.  
  132. // At this point we know enough to be able to sort the two
  133. // strings, so we don't need to compare any more parts.
  134. break;
  135. }
  136. }
  137.  
  138. // If we get here and `result` is still 0, then sort the shorter string
  139. // before the longer string.
  140. result || (result = a.length - b.length);
  141.  
  142. // Return the result, flipping the order if `options.descending` is
  143. // truthy.
  144. return options && options.descending ? -result : result;
  145. },
  146.  
  147. // -- Protected Methods ----------------------------------------------------
  148.  
  149. /**
  150. Splits a string into an array of alpha character and digit character parts.
  151.  
  152. @example
  153.  
  154. Y.ArraySort._splitAlphaNum('abc123def456');
  155. // => ['abc', '123', 'def', '456']
  156.  
  157. @method _splitAlphaNum
  158. @param {String} string String to split.
  159. @return {String[]} Array of alpha parts and digit parts.
  160. @protected
  161. @static
  162. @since 3.11.0
  163. **/
  164. _splitAlphaNum: function (string) {
  165. /*jshint boss:true */
  166. var parts = [],
  167. regex = /(\d+|\D+)/g,
  168. match;
  169.  
  170. while (match = regex.exec(string)) { // assignment
  171. parts.push(match[1]);
  172. }
  173.  
  174. return parts;
  175. }
  176. };
  177.