您可以将所有部分添加到固定大小的字符串中,然后对其进行排序,最后再次删除填充。
var arr = ['5.5.1', '4.21.0', '4.22.0', '6.1.0', '5.1.0', '4.5.0'];
arr = arr.map( a => a.split('.').map( n => +n+100000 ).join('.') ).sort()
.map( a => a.split('.').map( n => +n-100000 ).join('.') );
console.log(arr)
显然,您必须明智地选择数字 100000 的大小:它应该至少比最大的数字部分多一位。
使用正则表达式
当您使用该replace
方法的回调参数时,无需拆分和连接即可实现相同的操作:
var arr = ['5.5.1', '4.21.0', '4.22.0', '6.1.0', '5.1.0', '4.5.0'];
arr = arr.map( a => a.replace(/\d+/g, n => +n+100000 ) ).sort()
.map( a => a.replace(/\d+/g, n => +n-100000 ) );
console.log(arr)
只定义一次填充函数
由于填充及其反向函数非常相似,因此对两者使用一个函数f似乎是一个不错的练习,并使用一个额外的参数来定义“方向”(1=padding,-1=unpadding)。这导致了这个非常晦涩且极端的代码。考虑这只是为了好玩,而不是为了实际使用:
var arr = ['5.5.1', '4.21.0', '4.22.0', '6.1.0', '5.1.0', '4.5.0'];
arr = (f=>f(f(arr,1).sort(),-1)) ((arr,v)=>arr.map(a=>a.replace(/\d+/g,n=>+n+v*100000)));
console.log(arr);
使用sort
比较回调函数
您可以使用比较函数参数sort
来实现相同的目的:
arr.sort( (a, b) => a.replace(/\d+/g, n => +n+100000 )
.localeCompare(b.replace(/\d+/g, n => +n+100000 )) );
但是对于较大的阵列,这将导致性能降低。这是因为排序算法通常需要多次比较某个值,每次都与数组中的一个不同值。这意味着必须为相同的数字多次执行填充。出于这个原因,较大的数组首先在整个数组中应用填充,然后使用标准排序,然后再次删除填充会更快。
但是对于较短的数组,这种方法可能仍然是最快的。在这种情况下,所谓的自然排序选项——可以通过额外的参数实现localeCompare
——将比填充方法更有效:
var arr = ['5.5.1', '4.21.0', '4.22.0', '6.1.0', '5.1.0', '4.5.0'];
arr = arr.sort( (a, b) => a.localeCompare(b, undefined, { numeric:true }) );
console.log(arr);
有关填充和一元加号的更多信息
要了解填充是如何工作的,请查看它生成的中间结果:
[ "100005.100005.100001", "100004.100021.100000", "100004.100022.100000",
"100006.100001.100000", "100005.100001.100000" ]
关于表达式+n+100000
,请注意,第一个+
是一元加号,是将字符串编码的十进制数转换为其等效数字的最有效方法。添加 100000 使号码具有固定位数。当然,它也可以是 200000 或 300000。请注意,此添加不会更改数字按数字排序时的顺序。
以上只是填充字符串的一种方法。有关其他一些替代方案,请参阅此问答。