JavaScript column sorting
What is the best way of sorting if the column values are:
Before SORTING:
CANCELLED,
v06.*,
INDEPENDENT,
v06.00,
v06.00.01,
v06.01,
v06.02,
v06.00.xx,
v06.03,
v06.04,
ON HOLD,
v06.06,
v06.05,
v06.05.01,
v06.04.01,
v06.05.02,
v06.07,
v07.00,
After SORTING:
CANCELLED,
INDEPENDENT,
ON HOLD,
v06.*,
v06.00,
v06.00.01,
v06.00.xx,
v06.01,
v06.02,
v06.03,
v06.04,
v06.04.01,
v06.05开发者_如何转开发,
v06.05.01,
v06.05.02,
v06.06,
v06.07,
v07.00
Thanks in advance, Joseph
First sort it alphabetically ascending (by the 'default' sort - or sort()
without passing a function), then sort it numerically. That said, I'm sure there is a better way:
function sortNumber(a, b) {
return a - b;
}
var arr = [
"v07.00", "CANCELLED", "v06.*", "v06.04.01", "INDEPENDENT", "v06.00", "v06.00.01",
"v06.01", "v06.02", "v06.00.xx", "v06.03", "v06.04", "ON HOLD",
"v06.06", "v06.05", "v06.05.01", "v06.05.02",
"v06.07",
];
alert(arr.sort().sort(sortNumber).join("\n"));
Demo: http://jsfiddle.net/karim79/rY8Du/1/
Assuming your "column values" are in an Array
, use Array.sort with a custom compareFunction
to define the ordering as you want.
var columnValues = [
"CANCELLED", "v06.*", "INDEPENDENT", "v06.00", "v06.00.01",
"v06.01", "v06.02", "v06.00.xx", "v06.03", "v06.04", "ON HOLD",
"v06.06", "v06.05", "v06.05.01", "v06.04.01", "v06.05.02",
"v06.07", "v07.00" ];
columnValues.sort(function(a, b) {
if (a is less than b by some ordering criterion)
return -1;
if (a is greater than b by the ordering criterion)
return 1;
// a must be equal to b
return 0;
});
Edit here's a long-winded compareFunction
that seems to do what you want, at least for the example you give:
function(a, b) {
if (a==b) {
return 0;
}
if (a.length && a[0]=='v' && b.length && b[0]=='v') {
// Both strings are version strings.
// Do special case version matching.
var aParts = a.substring(1).split('.'),
bParts = b.substring(1).split('.'),
l = Math.max(a.length, b.length),
i = 0;
for (;i<l;i++) {
var aPart = aParts[i],
bPart = bParts[i];
if (aPart == '*' && bPart != '*') {
return -1;
}
if (bPart == '*' && aPart != '*') {
return 1;
}
if (aPart == 'xx' && bPart != 'xx') {
return 1;
}
if (bPart == 'xx' && aPart != 'xx') {
return -1;
}
var aNum = parseInt(aPart,10),
bNum = parseInt(bPart,10);
if (aNum < bNum) {
return -1;
}
if (aNum > bNum) {
return 1;
}
// Same so far, try next part
}
// One must be longer than the other.
return (aParts.length < bParts.length) ? -1 : 1
}
// Simple alphabetic comparison
if (a < b)
return -1;
if (a > b)
return 1;
}
Demo: http://jsfiddle.net/daybarr/h6nmg/
Once you get the column into an array you can use any natural sort method, but you'll need to write a couple extra lines to sort the '*' the way you want.
Here is one sample-
function natSort(as, bs){
var a, b, a1, b1, i= 0, L, rx= /(\d+)|(\D+)/g, rd= /\d/;
if(isFinite(as) && isFinite(bs)) return as - bs;
a= String(as).toLowerCase();
b= String(bs).toLowerCase();
if(a=== b) return 0;
if(!(rd.test(a) && rd.test(b))) return a> b? 1: -1;
a=a.replace('*','0'); // or possibly sort any non alpha nums first:
b=b.replace('*','0'); // replace(/[^\w\.]/g,'0');
a= a.match(rx);
b= b.match(rx);
L= a.length> b.length? b.length: a.length;
while(i < L){
a1= a[i];
b1= b[i++];
if(a1!== b1){
if(isFinite(a1) && isFinite(b1)){
if(a1.charAt(0)=== "0") a1= "." + a1;
if(b1.charAt(0)=== "0") b1= "." + b1;
return a1 - b1;
}
else return a1> b1? 1: -1;
}
}
return a.length - b.length;
}
var v= "v06.05,ON HOLD,v07.00,INDEPENDENT,v06.07,v06.03,v06.*,v06.05.02,v06.05.01,"+
"v06.00.xx,v06.00,CANCELLED,v06.02,v06.04,v06.00.01,v06.06,v06.01,v06.04.01";
v=v.split(/, */);
'before sort:\n'+v.join(',\n')+'\n\nafter sort:\n'+ v.sort(natSort).join(',\n')
/* returned value:
before sort:
v06.05,
ON HOLD,
v07.00,
INDEPENDENT,
v06.07,
v06.03,
v06.*,
v06.05.02,
v06.05.01,
v06.00.xx,
v06.00,
CANCELLED,
v06.02,
v06.04,
v06.00.01,
v06.06,
v06.01,
v06.04.01
after sort:
CANCELLED,
INDEPENDENT,
ON HOLD,
v06.*,
v06.00,
v06.00.01,
v06.00.xx,
v06.01,
v06.02,
v06.03,
v06.04,
v06.04.01,
v06.05,
v06.05.01,
v06.05.02,
v06.06,
v06.07,
v07.00
*/
精彩评论