我想对字符串数组进行排序(在JavaScript中),这样字符串中的数字组就可以作为整数而不是字符串进行比较,我不担心有符号或浮点数。
例如,结果应为["a1b3","a9b2","a10b2","a10b11"]
,而不是["a1b3","a10b11","a10b2","a9b2"]
最简单的方法似乎是在数字组周围的边界上分割每个字符串。有没有一种模式可以传递给String.split来在字符边界上分割而不删除任何字符?"abc11def22ghi".split(/?/) = ["abc","11","def","22","ghi"];
或者,有没有另一种不涉及拆分字符串的方法来比较字符串,比如用前导零填充所有数字组,使它们具有相同的长度?"aa1bb" => "aa00000001bb", "aa10bb" => "aa00000010bb"
我使用的是任意字符串,而不是具有特定数字组排列的字符串。
我喜欢Gaby的/(\d+)/
one liner来分割数组,这向后兼容性有多好?
解析一次字符串的解决方案可以用来重建原始字符串,这比这个比较函数要高效得多,没有一个答案处理一些以数字开头的字符串,而另一些则不处理,但这很容易补救,而且在原始问题中没有明确说明。
["a100", "a20", "a3", "a3b", "a3b100", "a3b20", "a3b3", "!!", "~~", "9", "10", "9.5"].sort(function (inA, inB) {
var result = 0;
var a, b, pattern = /(\d+)/;
var as = inA.split(pattern);
var bs = inB.split(pattern);
var index, count = as.length;
if (('' === as[0]) === ('' === bs[0])) {
if (count > bs.length)
count = bs.length;
for (index = 0; index < count && 0 === result; ++index) {
a = as[index]; b = bs[index];
if (index & 1) {
result = a - b;
} else {
result = !(a < b) ? (a > b) ? 1 : 0 : -1;
}
}
if (0 === result)
result = as.length - bs.length;
} else {
result = !(inA < inB) ? (inA > inB) ? 1 : 0 : -1;
}
return result;
}).toString();
结果:"!!,9,9.5,10,a3,a3b,a3b3,a3b20,a3b100,a20,a100,~~"
7条答案
按热度按时间wswtfjt71#
另一个变体是使用带有numeric选项的
Intl.Collator
示例:iecba09b2#
我想这就是你想要的
d8tt03nd3#
假设您只想按每个数组条目中的位数进行数字排序(忽略非位数),可以使用以下代码:
它使用了一个自定义的排序函数,在每次被要求进行比较时,该函数会删除数字并将其转换为数字。http://jsfiddle.net/jfriend00/t87m2/ .
x6yk4ghg4#
使用此比较函数进行排序...
语法
在http://jsfiddle.net/h9Rqr/7/上有一个演示。
3zwtqj6y5#
Here's a more complete solution,根据字符串中的字母和数字进行排序
tzcvj98z6#
我需要一种方法来获取一个混合字符串,并创建一个可以在其他地方排序的字符串,这样数字就可以按数字排序,字母则按字母顺序排序。基于上面的答案,我创建了下面的代码,它以我可以理解的方式填充所有数字,无论它们出现在字符串中的任何位置。
bvhaajcl7#
除非您创建了自定义算法,否则排序将从左到右进行。字母或数字是先比较数字,然后比较字母。
然而,你想完成的事情,如你自己的例子(a1,a9,a10)* 永远不会发生 *。这将需要你事先知道数据,并在应用排序之前以各种可能的方式分割字符串。
最后一个备选办法是:
a)每当存在从字母到数字的改变时,从左到右断开每个字符串,反之亦然;& B)然后从 * 右到左 * 开始对这些组进行排序。这将是一个非常苛刻的算法。可以做到!
最后,如果你是原始“文本”的“生成者”,你应该考虑对a1 a9 a10可以输出为a01 a09 a10的输出进行规范化。这样你就可以完全控制算法的最终版本。