2020年(大多数时候)正确的JavaScript答案
Nina Scholz在2020年3月和Sid Vishnoi在2020年4月都给出了现代的答案:
var versions = ["2.0.1", "2.0", "1.0", "1.0.1", "2.0.0.1"];
versions.sort((a, b) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: 'base' })
);
console.log(versions);
localCompare已经存在一段时间了
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Collator/Collator
但是1.0a和1.0.1呢
localCompare不能解决这个问题,仍然返回1.0.1,1.0a
迈克尔·迪尔(Michael Deal)在他的(略长且复杂的)解决方案中已经在2013年解决了这个问题
他将数字转换为另一种进位,以便更好地排序
他的回答让我思考……
666 -不要用数字思考- 999
排序是基于ASCII值的字母数字排序,所以让我们(ab)使用ASCII作为“基”
我的解决方案是将1.0.2.1到b.a.c.b转换为bacb,然后排序
这解决了1.1 vs. 1.0.0.0.1: bb vs. baaab
立即用baa和bab符号解决了1.0a和1.0.1排序问题
转换是通过:
const str = s => s.match(/(\d+)|[a-z]/g)
.map(c => c == ~~c ? String.fromCharCode(97 + c) : c);
=计算ASCII值0…999数字,否则连字母
1.0 > > >(“0”,“1”” " ] >>> [ " b”、“”、“”)
为了便于比较,没有必要使用.join("")将其连接到一个字符串。
Oneliner
const sortVersions=(x,v=s=>s.match(/(\d+)|[a-z]/g)
.map(c=>c==~~c?String.fromCharCode(97+c):c))
=>x.sort((a,b)=>v(b)<v(a)?1:-1)
测试代码片段:
function log(label,val){
document.body.append(label,String(val).replace(/,/g," - "),document.createElement("BR"));
}
let v = ["1.90.1", "1.9.1", "1.89", "1.090", "1.2", "1.0a", "1.0.1", "1.10", "1.0.0a"];
log('not sorted input :',v);
v.sort((a, b) => a.localeCompare(b,undefined,{numeric:true,sensitivity:'base' }));
log(' locale Compare :', v); // 1.0a AFTER 1.0.1
const str = s => s.match(/(\d+)|[a-z]/g)
.map(c => c == ~~c ? String.fromCharCode(97 + c) : c);
const versionCompare = (a, b) => {
a = str(a);
b = str(b);
return b < a ? 1 : a == b ? 0 : -1;
}
v.sort(versionCompare);
log('versionCompare:', v);
注意1.090是如何在两个结果中排序的。
我的代码不会解决一个答案中提到的001.012.001符号,但是localeCompare正确地解决了这部分挑战。
你可以结合这两种方法:
当涉及字母时,使用.localCompare或versionCompare进行排序
最终的JavaScript解决方案
const sortVersions = (
x,
V = s => s.match(/[a-z]|\d+/g)。Map (c => c==~~c ?String.fromCharCode(97 + c): c)
=> x.sort((a, b) => (a + b).match(/[a-z]/)
? V (b) < V (a) ?1: -1
: a.localeCompare(b, 0, {numeric: true}))
让v =[" 1.90.1”、“1.090”、“1.0”、“1.0.1”,“1.0.0a”,“1.0.0b”、“1.0.0.1”);
console.log (sortVersions (v));