Reputation: 843
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;
});
}
Upvotes: 13
Views: 9677
Reputation: 1913
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>
Upvotes: 0
Reputation: 1090
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
Upvotes: 0
Reputation: 105029
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())
});
}
Upvotes: 8
Reputation: 1731
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]
.
Upvotes: 1