Javascript:自然排序的字母数字字符串
我正在寻找最简单的方法来排序由数字和文本组成的数组,以及它们的组合。Javascript:自然排序的字母数字字符串
E.g.
'123asd'
'19asd'
'12345asd'
'asd123'
'asd12'
变成
'19asd'
'123asd'
'12345asd'
'asd12'
'asd123'
这将在组合使用与所述溶液another question I've asked here。
排序功能本身的作品,我需要的是一个函数,可以说'19asd'小于'123asd'。
我正在用JavaScript写这篇文章。
编辑:adormitu指出,我正在寻找的是自然排序
这现在可以在现代浏览器中使用localeCompare。通过传递numeric: true
选项,它会巧妙地识别数字。您可以使用sensitivity: 'base'
进行不区分大小写。经过Chrome,Firefox和IE11测试。
下面是一个例子。它返回1
,这意味着2后10云:
'10'.localeCompare('2', undefined, {numeric: true, sensitivity: 'base'})
出于性能方面的分拣大量的字符串时,文章说:
在比较大的数字的字符串,如在分拣大数组,最好创建一个Intl.Collator对象并使用它的compare属性提供的函数。
var collator = new Intl.Collator(undefined, {numeric: true, sensitivity: 'base'});
var myArray = ['1_Document', '11_Document', '2_Document'];
myArray.sort(collator.compare);
// myArray is now ['1_Document', '2_Document', '11_Document']
upvote为现代单线+1! – A1rPun 2016-11-07 16:45:00
真棒,很好的方法 – 2017-05-23 06:30:37
真棒,你解决了我的问题。谢谢 – 2017-09-11 06:05:07
功能所以你需要一个自然排序?
如果是这样,那么也许this script by Brian Huisman based on David koelle's work将是你所需要的。
好像布赖恩·豪氏威马的解决方案现在直接托管在大卫Koelle的博客:
对值进行比较,你可以使用一个比较方法 -
function naturalSorter(as, bs){
var a, b, a1, b1, i= 0, n, L,
rx=/(\.\d+)|(\d+(\.\d+)?)|([^\d.]+)|(\.\D+)|(\.$)/g;
if(as=== bs) return 0;
a= as.toLowerCase().match(rx);
b= bs.toLowerCase().match(rx);
L= a.length;
while(i<L){
if(!b[i]) return 1;
a1= a[i],
b1= b[i++];
if(a1!== b1){
n= a1-b1;
if(!isNaN(n)) return n;
return a1>b1? 1:-1;
}
}
return b[i]? -1:0;
}
但为了快速排序ng数组,在排序之前对数组进行索引,因此您只需执行一次小写转换和正则表达式 而不是每一步中的排序。
function naturalSort(ar, index){
var L= ar.length, i, who, next,
isi= typeof index== 'number',
rx= /(\.\d+)|(\d+(\.\d+)?)|([^\d.]+)|(\.(\D+|$))/g;
function nSort(aa, bb){
var a= aa[0], b= bb[0], a1, b1, i= 0, n, L= a.length;
while(i<L){
if(!b[i]) return 1;
a1= a[i];
b1= b[i++];
if(a1!== b1){
n= a1-b1;
if(!isNaN(n)) return n;
return a1>b1? 1: -1;
}
}
return b[i]!= undefined? -1: 0;
}
for(i= 0; i<L; i++){
who= ar[i];
next= isi? ar[i][index] || '': who;
ar[i]= [String(next).toLowerCase().match(rx), who];
}
ar.sort(nSort);
for(i= 0; i<L; i++){
ar[i]= ar[i][1];
}
}
大厦@Adrien要我们回答以上,并使用该Brian Huisman & David koelle创建的代码,这里是一个修改的原型分拣对象的数组:
//Usage: unsortedArrayOfObjects.alphaNumObjectSort("name");
//Test Case: var unsortedArrayOfObjects = [{name: "a1"}, {name: "a2"}, {name: "a3"}, {name: "a10"}, {name: "a5"}, {name: "a13"}, {name: "a20"}, {name: "a8"}, {name: "8b7uaf5q11"}];
//Sorted: [{name: "8b7uaf5q11"}, {name: "a1"}, {name: "a2"}, {name: "a3"}, {name: "a5"}, {name: "a8"}, {name: "a10"}, {name: "a13"}, {name: "a20"}]
// **Sorts in place**
Array.prototype.alphaNumObjectSort = function(attribute, caseInsensitive) {
for (var z = 0, t; t = this[z]; z++) {
this[z].sortArray = new Array();
var x = 0, y = -1, n = 0, i, j;
while (i = (j = t[attribute].charAt(x++)).charCodeAt(0)) {
var m = (i == 46 || (i >=48 && i <= 57));
if (m !== n) {
this[z].sortArray[++y] = "";
n = m;
}
this[z].sortArray[y] += j;
}
}
this.sort(function(a, b) {
for (var x = 0, aa, bb; (aa = a.sortArray[x]) && (bb = b.sortArray[x]); x++) {
if (caseInsensitive) {
aa = aa.toLowerCase();
bb = bb.toLowerCase();
}
if (aa !== bb) {
var c = Number(aa), d = Number(bb);
if (c == aa && d == bb) {
return c - d;
} else {
return (aa > bb) ? 1 : -1;
}
}
}
return a.sortArray.length - b.sortArray.length;
});
for (var z = 0; z < this.length; z++) {
// Here we're deleting the unused "sortArray" instead of joining the string parts
delete this[z]["sortArray"];
}
}
成像一个8位数的填充函数,分别将'123asd'和'19asd'转换为'00000123asd'和'00000019asd'。使用这些版本的字符串将帮助我们对“19asd”进行排序,使其出现在“123asd”之前。
我们可以使用正则表达式/\d+/g
,以帮助找到所有需要补齐的数字:
str.replace(/\d+/g, pad)
下面演示了使用这种技术的排序:
var list = [
'123asd',
'19asd',
'12345asd',
'asd123',
'asd12'
];
function pad(n) { return ("00000000" + n).substr(-8); }
function natural_expand(a) { return a.replace(/\d+/g, pad) };
function natural_compare(a, b) {
return natural_expand(a).localeCompare(natural_expand(b));
}
console.log(list.map(natural_expand).sort()); // intermediate values
console.log(list.sort(natural_compare)); // result
中间结果显示了natural_expand()例程的功能并为您提供了随后natural_compare程序将如何工作的理解:
[
"00000019asd",
"00000123asd",
"00asd",
"asd00000012",
"asd00000123"
]
输出:
[
"19asd",
"123asd",
"12345asd",
"asd12",
"asd123"
]
也看到'请问你http://stackoverflow.com/questions/51165做字符串比较在JavaScript'? /你怎么做字符串比较在JavaScript中 – 2014-09-26 12:19:58
原来的问题在2010年被问到,所以它不会令人惊讶:) – ptrn 2015-07-23 21:32:02