一个不完整的,相当严格的方式做到这一点可能是这样的:
'use strict';
const async = require('async');
let index = ['3.1.a', '3.2', '3.11', '3.1.c', '3.2.z'];
//'3.1.a' => ['3', '1', 'a']
function paragraphToSubstring(string, callback) {
async.map(string, (s, callback) => {
callback(null, s.split('.'));
}, (err, substrings) => {
callback(substrings);
});
}
//['3', '1', 'a'] => [3, 1, 1]
function substringToNumber(substrings) {
async.map(substrings, (e, callback) {
let i = parseInt(e);
//If e is a letter
if(isNaN(i)) {
//Take it's ASCII value
//If you need to support roman number, you'll have to make the check and transformation here
callback(null, e.charCodeAt(0));
} else {
callback(null, i);
}
})
}
function sort(paragraphs, callback) {
async.waterfall([
//Convert everything in array
(callback) => {
async.map(paragraphs, (p, callback) => {
paragraphToSubstring(p, (s) => {
callback(null, s);
});
}, (err, substrings) => {
callback(err, substrings)
});
},
//Convert everything in numbers
(substrings, callback) => {
async.map(substrings, (s, callback) => {
substringToNumber(s, (err, i) => {
callback(err, i);
});
}, (err, numbers) => {
callback(err, numbers);
});
}
//Sort
(numbers, callback) => {
callback(null, numbers.sort((a, b) => {
//Didn't found a way to support a undefinite number of element, settled on 3
let s1 = a[0] - b[0],
s2 = a[1] - b[1],
s3 = a[2] - b[2];
if(s1) {
return s1;
}
if(s2) {
return s2;
}
if(s3) {
return s3;
}
}));
}
], (err, sorted) {
callback(err, sorted);
});
}
有趣的练习做,我会回来以后有好转,当我还得有更多的工作时间。
你永远不需要比较一个数字和一个字母,是正确的吗?例如,'3.4'和'3.a'永远不需要比较? – apsillers
有些想法:你的子串是数字,在这种情况下,排序很简单,或者它们是字母。在这种情况下,您可以尝试执行查找表来对其进行编号转换。唯一的问题将是罗马数字('I','IV' ...),除非您找到一种方法可靠地将它们与简单字母区分开来。 – DrakaSAN
@apsillers - 是的,这是正确的。所有的子字符串将是相同的类型。 – qts