views:

405

answers:

5

When soritng an array made of a mix of strings, null values and zeros, i get the result not properly as exptected, null values seem to get sorted as if they were 'null' strings. I did this (tested on FireFox):

var arr1 = arr2 = [null, "b", "c", "d", null, "e", 0, "g", null, 0, "h", "i", "l", "m", "n", "o", "p", "ne", "nur", "nimbus"];

document.write("SORTED ARRAY:<br>");
arr1.sort();
arr1.forEach(function(val){document.write(val + "; ")});

And the result is:

SORTED ARRAY: 0; 0; b; c; d; e; g; h; i; l; m; n; ne; nimbus; null; null; null; nur; o; p;

Do you have an idea of how to make the null value be considered like empty string during the sorting of the array, so that they appear 1st in the sorted arry along with the zeros.

Thanks!

A: 

The browser is doing null.toString(); since null is an Object, this is pretty much Object.toString()... which would return "null"

Pass in a parameter to sort, as your comparison function [if the function returns something greater than 0, b is sorted lower than a]

function would basically be:

comparisonFunc = function(a, b)
{
 if((a === null) && (b === null)) return 0; //they're both null and equal
 else if((a === null) && (b != null)) return -1; //move a downwards
 else if((a != null) && (b === null)) return 1; //move b downwards
 else{
  //Lexicographical sorting goes here
 }
}
set.sort(comparisonFunc);
ItzWarty
A: 

You can pass the sort a sortfunction

array.sort(sortfunction)

where sortfunction does the comparison you need (regular sorting with null values being greater than others)

SP
A: 

Use a custom ordering function that handles null values this way.

arr1.sort(function(a, b) {
    if (a===null) a='';
    if (b===null) b='';

    if (''+a < ''+b) return -1;
    if (''+a > ''+b) return  1;

    return 0;
});
Alexandre Jasmin
That first line should of course read: if (a===null) a='';
Hans B PUFAL
@Hans Thanks edited
Alexandre Jasmin
+3  A: 

This will do what you want by converting everything to strings (in particular converting null to an empty string) and allowing JavaScript's built-in string comparison do the work:

arr2.sort( function(a, b) {
    a = (a === null) ? "" : "" + a;
    b = (b === null) ? "" : "" + b;
    return a > b ? 1 : ( a === b ? 0 : -1 );
} );
Tim Down
+1 For Ternary Terseness
Alexandre Jasmin
This will fail to sort properly if he has numbers. You need some more ternaries.
andras
@andras If by properly you mean that 20 comes before 5 the default sort has the same issue
Alexandre Jasmin
@andras, @Alexandre: The original question does say the array has zeros, strings and nulls so I'm not sure correctly handling numbers is required, but I take your point.
Tim Down
@Tim: sounds great thanks! What about doing: a = a || ""; b = b || "";
Marco Demajo
@Marco: Two problems with that: first, zeroes and `null` will both be converted to an empty string, meaning the sort will not distinguish between nulls and zeroes (unless that isn't a problem for you). Second, non-zero numbers will not be converted to strings, and the comparison of a number with a string that cannot be converted into a number (such as `"d"`) always returns `false`, so will not order as you expect.
Tim Down
@Tim Down: thanks and +1, you are perfeclty right expecially the SECOND point.
Marco Demajo
+1  A: 
[null, "b", "c", "d", null, "e", 0, "g", null, 0, "h", "i", "l", "m", "n", "o", "p", "ne", "nur", "nimbus"].sort(function (a,b) { 
   return a === null ? -1 : b === null ? 1 : a.toString().localeCompare(b);
});
robert
Ah yes, I forgot about `localeCompare`. +1.
Tim Down