好的,这是我解决这个问题的尝试。该代码现在非常冗长,但我正在研究如何缩小它,并将在我进行时更新我的答案。这应该足以解决问题,让您移动。我会将我的代码作为节点模块发布,因为那是你的环境。
它的要点是它将项目分解成可以单独分类的单独部分。它并行循环这些数组中的每一个,一旦发现不匹配,它将运行基本的排序比较。
排序器.js
// regex patterns to determine how to "parse" an input item
var patterns = [
/^([a-zA-Z]+)$/, // only letters
/^(\d+)$/, // only contains an integer
/^(\d+)\-\d+$/, // contains 2 integers separated by a hyphen
/^(\d+)([a-z]+)?\-(\d+)([a-z]+)?$/, // contains a 2 integer/letter combos separated by a hyphen
/^(\d+)([a-z]+)$/ // contains an integer followed by letters
];
function itemComparator(item) {
var len = patterns.length,
matches, x, regex;
for (x = 0; x < len; x++) {
regex = patterns[x];
if (regex.test(item)) {
matches = item.match(regex).slice(1);
if (/^\d+$/.test(matches[0])) {
matches[0] = parseInt(matches[0], 10);
}
return matches;
}
}
throw new Error("could not parse item for comparison: " + item);
}
module.exports = function (a, b) {
var compA = itemComparator(a),
compB = itemComparator(b),
x, len, tmpA, tmpB, typeA, typeB; // tmp vars
// find the largest size, so we don't miss anything
len = Math.max(compA.length, compB.length);
// loop each comp arr in parallel
for (x = 0; x < len; x += 1) {
// store for speed
tmpA = compA[x];
tmpB = compB[x];
typeA = typeof tmpA;
typeB = typeof tmpB;
// if the elements are not equal
if (tmpA !== tmpB) {
// then do the comparison, and stop the loop
if (typeA === typeB) {
return tmpA < tmpB ? -1 : 1;
} else if (typeA === "undefined") {
return -1;
} else if (typeB === "undefined") {
return 1;
} else if (typeA === "string") {
return -1;
} else if (typeB === "string") {
return 1;
} else {
console.warn("unexpected condition for %s (%s) and %s (%s)", tmpA, typeA, tmpB, typeB);
return 0;
}
}
}
};
测试.js
var sorter = require("./sorter"),
arr = [
'1a', 'aa', '2a', '2aa', '5-6', '1', '2', '3', 'DBA', 'bb',
'20', '2b', '7', '8', '125a', '33a-35', 'ABC',
'3aaa-4c', '3aaa-52d', 'AA', 'c', '5dd', 'aa'
];
console.log(arr.sort(sorter));
// [ 'AA',
// 'ABC',
// 'DBA',
// 'aa',
// 'aa',
// 'bb',
// 'c',
// '1',
// '1a',
// '2',
// '2a',
// '2aa',
// '2b',
// '3',
// '3aaa-4c',
// '3aaa-52d',
// '5-6',
// '5dd',
// '7',
// '8',
// '20',
// '33a-35',
// '125a' ]