So I have an array of arrays which contain only strings. The array of arrays is to be displayed as a table and may have over 1000 rows with 20 or more values in each.
eg:
var arr = [
["bob","12","yes"],
["joe","","no"],
["tim","19","no"],
["dan","","yes"],
["tim","",""],
["dan","0",""]
]
the strings may contain anything that can be represented as a string, including: " "
, ""
, "0"
or "00-00-00"
etc... and any column my be used for ordering.
I am sorting the arrays ascending and descending but some of the values I am sorting by are blank strings: ""
. How could I get the blank strings (only) to always be at the end of the new arrays in all modern browsers?
currently they are at the end when ascending but at the start when descending.
I am sorting like below (Yes I'm sure I can do it shorter too):
if (direction == "asc") {
SortedArr = arr.sort(function (a, b) {
if (a[colToSortBy] == '') {
return -1;
}
if (a[colToSortBy].toUpperCase() < b[colToSortBy].toUpperCase()) {
return -1;
}
if (a[colToSortBy].toUpperCase() > b[colToSortBy].toUpperCase()) {
return 1;
}
return 0;
});
} else {
SortedArr = arr.sort(function (a, b) {
if (a[colToSortBy] == '') {
return -1;
}
if (b[colToSortBy].toUpperCase() < a[colToSortBy].toUpperCase()) {
return -1;
}
if (b[colToSortBy].toUpperCase() > a[colToSortBy].toUpperCase()) {
return 1;
}
return 0;
});
}
So I have an array of arrays which contain only strings. The array of arrays is to be displayed as a table and may have over 1000 rows with 20 or more values in each.
eg:
var arr = [
["bob","12","yes"],
["joe","","no"],
["tim","19","no"],
["dan","","yes"],
["tim","",""],
["dan","0",""]
]
the strings may contain anything that can be represented as a string, including: " "
, ""
, "0"
or "00-00-00"
etc... and any column my be used for ordering.
I am sorting the arrays ascending and descending but some of the values I am sorting by are blank strings: ""
. How could I get the blank strings (only) to always be at the end of the new arrays in all modern browsers?
currently they are at the end when ascending but at the start when descending.
I am sorting like below (Yes I'm sure I can do it shorter too):
if (direction == "asc") {
SortedArr = arr.sort(function (a, b) {
if (a[colToSortBy] == '') {
return -1;
}
if (a[colToSortBy].toUpperCase() < b[colToSortBy].toUpperCase()) {
return -1;
}
if (a[colToSortBy].toUpperCase() > b[colToSortBy].toUpperCase()) {
return 1;
}
return 0;
});
} else {
SortedArr = arr.sort(function (a, b) {
if (a[colToSortBy] == '') {
return -1;
}
if (b[colToSortBy].toUpperCase() < a[colToSortBy].toUpperCase()) {
return -1;
}
if (b[colToSortBy].toUpperCase() > a[colToSortBy].toUpperCase()) {
return 1;
}
return 0;
});
}
Share
Improve this question
edited Nov 24, 2011 at 20:55
Chris J
asked Nov 24, 2011 at 11:18
Chris JChris J
8431 gold badge9 silver badges16 bronze badges
6
|
Show 1 more comment
4 Answers
Reset to default 8Empty strings at the end
Working example on JSFiddle that puts empty strings always at the end no matter whether order is ascending or descending. This may be a usability issue, but this is the solution:
if (direction == "asc") {
SortedArr = arr.sort(function (a, b) {
return (a[col] || "").toUpperCase().localeCompare((b[col] || "").toUpperCase())
});
} else {
SortedArr = arr.sort(function (a, b) {
return (b[col] || "!!!").toUpperCase().localeCompare((a[col] || "!!!").toUpperCase())
});
}
I think your problem comes from the fact that you're checking if a[colToSortBy]
is an emtpy string but you don't do it for b[colToSortBy]
.
I am writing an application that must work on IE, FF, Safari, Chrome, Opera, Desktop, Tablet (including iPad) & phones (including iPhone). This means I keep testing across browsers. I thus discovered that my sort procedure below wasn't working correctly in FF until I added the 'new section' part of the code. Reason being I did not take care of sorting when a numeric value is not supplied (dash, -). FF was also not working correctly with negative (-) values. This code now works perfectly across:
if (SortByID == 0) { //string values (Bank Name)
myValues.sort( function (a,b) {
var nameA = a[SortByID].toUpperCase(), nameB = b[SortByID].toUpperCase();
if (SortOrderID == 1) { //sort string ascending
if (nameA < nameB) { return -1; } else { if (nameA > nameB) { return 1; } }
} else { //sort string descending
if (nameA < nameB) { return 1; } else { if (nameA > nameB) { return -1; } }
}
return 0 //default return value (no sorting)
})
} else { //numeric values (Items)
myValues.sort(function (a, b) {
if (isNumber(a[SortByID]) && isNumber(b[SortByID])) { //
if (SortOrderID == 1) { //sort number ascending
return parseFloat(a[SortByID]) - parseFloat(b[SortByID]);
} else { //sort string descending
return parseFloat(b[SortByID]) - parseFloat(a[SortByID]);
}
} else { //one of the values is not numeric
//new section
if (!isNumber(a[SortByID])) {
if (SortOrderID == 1) { //sort number ascending
return -1;
} else { //sort number descending
return 1;
}
} else {
if (!isNumber(b[SortByID])) {
if (SortOrderID == 1) { //sort number ascending
return 1;
} else { //sort number descending
return -1;
}
}
}//New section
return 0;
}
})
}
I know it is long, but it is simple enough for me to understand. I hope it also addresses the browser issue raised by Chris J. *isNumber is a simple function testing if value !isNAN
I used this way in my app...
You can tweak it to get the favorable result. we also have the Number.MAX_SAFE_INTEGER
var arr = [10, "", 8, "", 89, 72]
var min = Number.MIN_SAFE_INTEGER
var sorted = arr.sort(function (a,b) {
return (a || min) - (b || min)
})
var cons = document.getElementById("console")
cons.innerText = "Ascending " + JSON.stringify(sorted) + "\n" + "Descending " + JSON.stringify(sorted.reverse())
<html>
<head></head>
<body>
<p id="console"></p>
</body>
</html>
return 1
in the firstif
of both sorts when checking empty strings? Doesn't that do the trick? – Robert Koritnik Commented Nov 24, 2011 at 11:25return -1
toreturn 1
in ifs checking empty strings and they indeed got to the end. You've probably sorted some other column to get them in the middle. The first column (array index 0 since index is zero based) seems to do just that. – Robert Koritnik Commented Nov 24, 2011 at 11:35