/** * Returns a number indicating whether a reference string comes before, or after, * or is the same as the given string in natural sort order. * * See: https://en.wikipedia.org/wiki/Natural_sort_order * */ export function naturalCompare(aStr, bStr) { let aIndex = 0; let bIndex = 0; while (aIndex < aStr.length && bIndex < bStr.length) { let aChar = aStr.charCodeAt(aIndex); let bChar = bStr.charCodeAt(bIndex); if (isDigit(aChar) && isDigit(bChar)) { let aNum = 0; do { ++aIndex; aNum = aNum * 10 + aChar - DIGIT_0; aChar = aStr.charCodeAt(aIndex); } while (isDigit(aChar) && aNum > 0); let bNum = 0; do { ++bIndex; bNum = bNum * 10 + bChar - DIGIT_0; bChar = bStr.charCodeAt(bIndex); } while (isDigit(bChar) && bNum > 0); if (aNum < bNum) { return -1; } if (aNum > bNum) { return 1; } } else { if (aChar < bChar) { return -1; } if (aChar > bChar) { return 1; } ++aIndex; ++bIndex; } } return aStr.length - bStr.length; } const DIGIT_0 = 48; const DIGIT_9 = 57; function isDigit(code) { return !isNaN(code) && DIGIT_0 <= code && code <= DIGIT_9; }