Javascript sorting question
-
I found this piece of code in a tutorial, and it makes no sense to me. How does that function sortNumber(a,b) do anything? It looks like its just returning the value of a-b, which to me does not tell much of how to sort anything. Please enlighten me. Thanks!
<html> <body> <script type="text/javascript"> function sortNumber(a, b) { return b - a ; } var n = ["10", "5", "40", "25", "100", "1"]; document.write(n.sort(sortNumber)); </script> </body> </html>
-
n is an Array.
JavaScript Array's have a built-in sort method.
n.sort();
which accepts an optional function (named sortNumber is this case.)
n.sort(sortNumber);
or using an anonymous function:
n.sort(function(a,b){return(a-b);})
The function passed to the sort function just describes how to compare 2 things, the Array.sort function iterates the array and uses the compare function on each element in turn to sort the collection. It expects a return value of any of <0, 0, or >0 meaning less than, equal to, or greater than.
There is also some type conversions going on - Strings to numbers - which happens frequently in JavaScript and you really need to keep that in mind.
Ruby Array's sort method can also accept a block in a similar way.
a = [2, 3, 1] a.sort { |a, b| b <=> a} ==> [3, 2, 1]
-
var n = ["10", "5", "40", "25", "100", "1"]; document.write(n.sort());
will return the array 'n' sorted in alphanumerical order.
function sortNumber(a, b) { return (a - b) ; } var n = ["10", "5", "40", "25", "100", "1"]; document.write(n.sort(sortNumber));
will return the array 'n' sorted in ascending numerical order.
Your posted version ...return (b - a)
... should 'reverse it' - i.e. in descending numerical order ?
However, the array 'n' would then be more sensibly a list of numbers rather than strings, because the stings sort anyway ???
To 'reverse' a strings array so it's descending you can use.reverse
on it after the initial ascending.sort
???? -
@jim said:
It expects a return value of any of <1, 0, or >1 for less than, equal to, or greater than.
Aha, that was the missing piece in my head. I couldn't figure out what the point of the subtraction was. That makes perfect sense now.
Thanks for the responses guys, always so helpful!
Chris
-
While on the topic of sorting, I found a natural sorting method for array of strings:
/* * Natural Sort algorithm for Javascript - Version 0.4 - Released under MIT license * Author; Jim Palmer (based on chunking idea from Dave Koelle) * Contributors; Mike Grier (mgrier.com), Clint Priest, Kyle Adams */ function naturalSort(a, b) { // setup temp-scope variables for comparison evauluation var re = /(^[0-9]+\.?[0-9]*[df]?e?[0-9]?$|^0x[0-9a-f]+$|[0-9]+)/gi, sre = /(^[ ]*|[ ]*$)/g, hre = /^0x[0-9a-f]+$/i, ore = /^0/, // convert all to strings and trim() x = a.toString().replace(sre, '') || '', y = b.toString().replace(sre, '') || '', // chunk/tokenize xN = x.replace(re, '\0$1\0').replace(/\0$/,'').replace(/^\0/,'').split('\0'), yN = y.replace(re, '\0$1\0').replace(/\0$/,'').replace(/^\0/,'').split('\0'), // hex or date detection xD = parseInt(x.match(hre)) || (new Date(x)).getTime(), yD = parseInt(y.match(hre)) || xD && (new Date(y)).getTime() || null; // natural sorting of hex or dates - prevent '1.2.3' valid date if ( y.indexOf('.') < 0 && yD ) if ( xD < yD ) return -1; else if ( xD > yD ) return 1; // natural sorting through split numeric strings and default strings for(var cLoc=0, numS=Math.max(xN.length, yN.length); cLoc < numS; cLoc++) { // find floats not starting with '0', string or 0 if not defined (Clint Priest) oFxNcL = !(xN[cLoc] || '').match(ore) && parseFloat(xN[cLoc]) || xN[cLoc] || 0; oFyNcL = !(yN[cLoc] || '').match(ore) && parseFloat(yN[cLoc]) || yN[cLoc] || 0; // handle numeric vs string comparison - number < string - (Kyle Adams) if (isNaN(oFxNcL) !== isNaN(oFyNcL)) return (isNaN(oFxNcL)) ? 1 ; -1; // rely on string comparison if different types - i.e. '02' < 2 != '02' < '2' else if (typeof oFxNcL !== typeof oFyNcL) { oFxNcL += ''; oFyNcL += ''; } if (oFxNcL < oFyNcL) return -1; if (oFxNcL > oFyNcL) return 1; } return 0; }
-
@chris fullmer said:
@jim said:
It expects a return value of any of <1, 0, or >1 for less than, equal to, or greater than.
Aha, that was the missing piece in my head. I couldn't figure out what the point of the subtraction was. That makes perfect sense now.
Thanks for the responses guys, always so helpful!
Chris
Sure you realised Chris, but little typo in Jim's answer. So just for correctness:
compare function returning <0, 0, >0 representing 'less than', 'equal' or 'greater than'.
One small caveat when writing compare functions being driven by sort functions is that you must by rigourously consistent in your answers you return. ie if a<b then b>a. If you don't, you'll get an undefined array order - or even a crash in C++ etc.
-
oops. thanks Adam. Fixed in OP.
Advertisement