naturalCompare.mjs 1.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. /**
  2. * Returns a number indicating whether a reference string comes before, or after,
  3. * or is the same as the given string in natural sort order.
  4. *
  5. * See: https://en.wikipedia.org/wiki/Natural_sort_order
  6. *
  7. */
  8. export default function naturalCompare(aStr, bStr) {
  9. var aIdx = 0;
  10. var bIdx = 0;
  11. while (aIdx < aStr.length && bIdx < bStr.length) {
  12. var aChar = aStr.charCodeAt(aIdx);
  13. var bChar = bStr.charCodeAt(bIdx);
  14. if (isDigit(aChar) && isDigit(bChar)) {
  15. var aNum = 0;
  16. do {
  17. ++aIdx;
  18. aNum = aNum * 10 + aChar - DIGIT_0;
  19. aChar = aStr.charCodeAt(aIdx);
  20. } while (isDigit(aChar) && aNum > 0);
  21. var bNum = 0;
  22. do {
  23. ++bIdx;
  24. bNum = bNum * 10 + bChar - DIGIT_0;
  25. bChar = bStr.charCodeAt(bIdx);
  26. } while (isDigit(bChar) && bNum > 0);
  27. if (aNum < bNum) {
  28. return -1;
  29. }
  30. if (aNum > bNum) {
  31. return 1;
  32. }
  33. } else {
  34. if (aChar < bChar) {
  35. return -1;
  36. }
  37. if (aChar > bChar) {
  38. return 1;
  39. }
  40. ++aIdx;
  41. ++bIdx;
  42. }
  43. }
  44. return aStr.length - bStr.length;
  45. }
  46. var DIGIT_0 = 48;
  47. var DIGIT_9 = 57;
  48. function isDigit(code) {
  49. return !isNaN(code) && DIGIT_0 <= code && code <= DIGIT_9;
  50. }