Javascript 排序数组元素(带数字的字符串),自然排序
我有一个数组像Javascript 排序数组元素(带数字的字符串),自然排序,javascript,jquery,sorting,Javascript,Jquery,Sorting,我有一个数组像 ["IL0 Foo", "PI0 Bar", "IL10 Baz", "IL3 Bob says hello"] 需要对其进行排序,使其看起来像 ["IL0 Foo", "IL3 Bob says hello", "IL10 Baz", "PI0 Bar"] 我尝试了一个排序函数 function compare(a,b) { if (a < b) return -1; if (a > b) return 1; return 0; }
["IL0 Foo", "PI0 Bar", "IL10 Baz", "IL3 Bob says hello"]
需要对其进行排序,使其看起来像
["IL0 Foo", "IL3 Bob says hello", "IL10 Baz", "PI0 Bar"]
我尝试了一个排序函数
function compare(a,b) {
if (a < b)
return -1;
if (a > b)
return 1;
return 0;
}
我试着想一个可以工作的正则表达式,但我的头脑却无法理解它。如果有帮助的话,格式将始终是2个字母,x个数字,然后是任意数量的字符。不漂亮,但请检查前两个字符代码。如果全部相等,则解析并比较数字:
var arr = ["IL0 Foo", "IL10 Baz", "IL3 Bob says hello", "PI0 Bar"];
arr.sort(function (a1, b1) {
var a = parseInt(a1.match(/\d+/g)[0], 10),
b = parseInt(b1.match(/\d+/g)[0], 10),
letterA = a1.charCodeAt(0),
letterB = b1.charCodeAt(0),
letterA1 = a1.charCodeAt(1),
letterB1 = b1.charCodeAt(1);
if (letterA > letterB) {
return 1;
} else if (letterB > letterA) {
return -1;
} else {
if (letterA1 > letterB1) {
return 1;
} else if (letterB1 > letterA1) {
return -1;
}
if (a < b) return -1;
if (a > b) return 1;
return 0;
}
});
var-arr=[“IL0-Foo”、“IL10-Baz”、“IL3-Bob打招呼”、“PI0-Bar”];
arr.sort(功能(a1、b1){
var a=parseInt(a1.match(/\d+/g)[0],10),
b=parseInt(b1.match(/\d+/g)[0],10),
字母A=a1.字符代码(0),
字母B=b1.字符编码(0),
字母a1=a1.字符代码(1),
字母b1=b1.字符编码(1);
如果(字母A>字母B){
返回1;
}否则如果(字母B>字母A){
返回-1;
}否则{
如果(字母A1>字母B1){
返回1;
}否则如果(字母B1>字母A1){
返回-1;
}
如果(ab)返回1;
返回0;
}
});
var re=/([a-z]+)(\d+)(.+)/i;
var arr=[“il0foo”、“pi0bar”、“il10baz”、“il3bob说你好”];
变量顺序=arr.sort(函数(a,b){
var ma=a.匹配(re),
mb=b.匹配(re),
a_str=ma[1],
b_str=mb[1],
a_num=parseInt(ma[2],10),
b_num=parseInt(mb[2],10),
a_rem=ma[3],
b_rem=mb[3];
返回a_str>b_str?1:a_strb_num?1:a_numb_rem;
});
您可以执行如下正则表达式以获取字符串的非数字和数字部分:
var s = "foo124bar23";
s.match(/[^\d]+|\d+/g)
返回:[“foo”、“124”、“bar”、“23”]
然后,在比较函数中,您可以遍历两个字符串的各个部分,逐个比较它们。第一个不匹配部分确定整体比较的结果。对于每个部件,检查部件是否以数字开头,如果是,则在进行比较之前将其解析为数字。这称为“自然排序”,可以在JS中实现,如下所示:
函数自然比较(a,b){
var ax=[],bx=[];
a、 替换(/(\d+)(\d+)/g,函数(u,$1,$2){ax.push([$1 | | |无穷,$2 | |”“]);
b、 替换(/(\d+)|(\d+)/g,函数(_,$1,$2){bx.push([$1 | |无穷大,$2 | |”“]);
while(ax.length&&bx.length){
var an=ax.shift();
var bn=bx.shift();
var nn=(an[0]-bn[0])| | an[1]。localeCompare(bn[1]);
如果(nn)返回nn;
}
返回ax.length-bx.length;
}
/////////////////////////
测试=[
“img12.png”,
“img10.png”,
“img2.png”,
“img1.png”,
“img101.png”,
“img101a.png”,
“abc10.jpg”,
“abc10”,
“abc2.jpg”,
“20.jpg”,
"20",
“abc”,
“abc2”,
""
];
测试.排序(自然比较)
document.write(“+JSON.stringify(test,0,3))代码>再添加一个备选方案(为什么不添加):
var ary = ["IL0 Foo", "PI0 Bar", "IL10 Hello", "IL10 Baz", "IL3 Bob says hello"];
// break out the three components in to an array
// "IL10 Bar" => ['IL', 10, 'Bar']
function getParts(i){
i = i || '';
var parts = i.match(/^([a-z]+)([0-9]+)(\s.*)$/i);
if (parts){
return [
parts[1],
parseInt(parts[2], 10),
parts[3]
];
}
return []; // erroneous
}
ary.sort(function(a,b){
// grab the parts
var _a = getParts(a),
_b = getParts(b);
// trouble parsing (both fail = no shift, otherwise
// move the troubles element to end of the array)
if(_a.length == 0 && _b.length == 0) return 0;
if(_a.length == 0) return -1;
if(_b.length == 0) return 1;
// Compare letter portion
if (_a[0] < _b[0]) return -1;
if (_a[0] > _b[0]) return 1;
// letters are equal, continue...
// compare number portion
if (_a[1] < _b[1]) return -1;
if (_a[1] > _b[1]) return 1;
// numbers are equal, continue...
// compare remaining string
if (_a[2] < _b[2]) return -1;
if (_a[2] > _b[2]) return 1;
// strings are equal, continue...
// exact match
return 0;
});
var-ari=[“il0foo”、“pi0bar”、“il10hello”、“il10baz”、“il3bob说Hello”];
//将三个组件拆分为一个数组
//“IL10 Bar”=>['IL',10'Bar']
功能部件(一){
i=i | |'';
var parts=i.match(/^([a-z]+)([0-9]+)(\s.*)$/i);
如有(部分){
返回[
第[1]部分,
parseInt(第[2]和第10部分),
第[3]部
];
}
返回[];//错误
}
ary.sort(函数(a,b){
//抓住零件
var _a=getParts(a),
_b=零件(b);
//解析问题(两个都失败=无移位,否则
//将元素移动到阵列的末尾)
if(_a.length==0&&u b.length==0)返回0;
如果(_a.length==0)返回-1;
如果(_b.length==0)返回1;
//比较字母部分
if(_a[0]<_b[0])返回-1;
if(_a[0]>_b[0])返回1;
//字母是相等的,继续。。。
//比较数字部分
如果(_a[1]<_b[1])返回-1;
如果(_a[1]>_b[1])返回1;
//数字相等,继续。。。
//比较剩余字符串
如果(_a[2]<_b[2])返回-1;
if(_a[2]>_b[2])返回1;
//字符串相等,请继续。。。
//精确匹配
返回0;
});
我非常喜欢乔治的解决方案,但我需要下划线(“u”)在数字之前排序。下面是我如何修改他的代码:
var chunkRgx=/(+)|([0-9]+)|([^0-9]+)/g;
函数自然比较(a,b){
var ax=[],bx=[];
a、 替换(chunkRgx,函数(_,$1,$2,$3){
ax.push([$1 | | |“0”、$2 | | | |无穷大、$3 | | |“]))
});
b、 替换(chunkRgx,函数(_,$1,$2,$3){
bx.push([$1 | | |“0”,$2 | | |无穷大,$3 | | |“]))
});
while(ax.length&&bx.length){
var an=ax.shift();
var bn=bx.shift();
var nn=an[0]。本地比较(bn[0])||
(an[1]-bn[1])||
an[2]。localeCompare(bn[2]);
如果(nn)返回nn;
}
返回ax.length-bx.length;
}
/////////////////////////
测试=[
“img12.png”,
“img10.png”,
“img2.png”,
“img1.png”,
“img101.png”,
“img101a.png”,
“abc10.jpg”,
“abc10”,
“abc2.jpg”,
“20.jpg”,
"20",
“abc”,
“abc2”,
“_abc”,
“_ab_c”,
“_ab___c”,
“_abc_d”,
“阿伯”,
“abc”,
“_ab_cd”,
""
];
测试.排序(自然比较)
document.write(“+JSON.stringify(test,0,3))用前导零对字符串中的数字进行编码,然后正常排序
var ary = ["IL0 Foo", "PI0 Bar", "IL10 Hello", "IL10 Baz", "IL3 Bob says hello"];
// break out the three components in to an array
// "IL10 Bar" => ['IL', 10, 'Bar']
function getParts(i){
i = i || '';
var parts = i.match(/^([a-z]+)([0-9]+)(\s.*)$/i);
if (parts){
return [
parts[1],
parseInt(parts[2], 10),
parts[3]
];
}
return []; // erroneous
}
ary.sort(function(a,b){
// grab the parts
var _a = getParts(a),
_b = getParts(b);
// trouble parsing (both fail = no shift, otherwise
// move the troubles element to end of the array)
if(_a.length == 0 && _b.length == 0) return 0;
if(_a.length == 0) return -1;
if(_b.length == 0) return 1;
// Compare letter portion
if (_a[0] < _b[0]) return -1;
if (_a[0] > _b[0]) return 1;
// letters are equal, continue...
// compare number portion
if (_a[1] < _b[1]) return -1;
if (_a[1] > _b[1]) return 1;
// numbers are equal, continue...
// compare remaining string
if (_a[2] < _b[2]) return -1;
if (_a[2] > _b[2]) return 1;
// strings are equal, continue...
// exact match
return 0;
});
var naturalSort=函数(a,b){
a=(''+a).replace(/(\d+)/g,函数(n){return('0000'+n).slice(-5)});
b=(''+b).replace(/(\d+)/g,函数(n){return('0000'+n).slice(-5)});
返回a.localeCompare(b);
}
var naturalSortModern=函数(a,b){
return(“”+a).localeCompare(“”+b),'en',{numeric:true});
}
console.dir([“il0foo”、“pi0bar”、“il10baz”、“il3bob说你好”].sort(naturalSort));
console.dir(([“il0foo”,“pi0bar”,“il10baz”,“il3bob说你好])排序
var ary = ["IL0 Foo", "PI0 Bar", "IL10 Hello", "IL10 Baz", "IL3 Bob says hello"];
// break out the three components in to an array
// "IL10 Bar" => ['IL', 10, 'Bar']
function getParts(i){
i = i || '';
var parts = i.match(/^([a-z]+)([0-9]+)(\s.*)$/i);
if (parts){
return [
parts[1],
parseInt(parts[2], 10),
parts[3]
];
}
return []; // erroneous
}
ary.sort(function(a,b){
// grab the parts
var _a = getParts(a),
_b = getParts(b);
// trouble parsing (both fail = no shift, otherwise
// move the troubles element to end of the array)
if(_a.length == 0 && _b.length == 0) return 0;
if(_a.length == 0) return -1;
if(_b.length == 0) return 1;
// Compare letter portion
if (_a[0] < _b[0]) return -1;
if (_a[0] > _b[0]) return 1;
// letters are equal, continue...
// compare number portion
if (_a[1] < _b[1]) return -1;
if (_a[1] > _b[1]) return 1;
// numbers are equal, continue...
// compare remaining string
if (_a[2] < _b[2]) return -1;
if (_a[2] > _b[2]) return 1;
// strings are equal, continue...
// exact match
return 0;
});