By peirix


2009-06-30 10:43:11 8 Comments

Trying to get the highest and lowest value from an array that I know will contain only integers seems to be harder than I thought.

var numArray = [140000, 104, 99];
numArray = numArray.sort();
alert(numArray)

I'd expect this to show 99, 104, 140000. Instead it shows 104, 140000, 99. So it seems the sort is handling the values as strings.

Is there a way to get the sort function to actually sort on integer value?

21 comments

@Anshul Chaurasia 2019-11-22 06:09:54

As sort method converts Array elements into string. So, below way also works fine with decimal numbers with array elements.

let productPrices = [10.33, 2.55, 1.06, 5.77];
console.log(productPrices.sort((a,b)=>a-b));

And gives you the expected result.

@aks 2009-06-30 10:47:04

By default, the sort method sorts elements alphabetically. To sort numerically just add a new method which handles numeric sorts (sortNumber, shown below) -

function sortNumber(a, b) {
  return a - b;
}

var numArray = [140000, 104, 99];
numArray.sort(sortNumber);

console.log(numArray);

In ES6, you can simplify this with arrow functions:

numArray.sort((a, b) => a - b); // For ascending sort
numArray.sort((a, b) => b - a); // For descending sort

Documentation:

Mozilla Array.prototype.sort() recommends this compare function for arrays that don't contain Infinity or NaN. (Because Inf - Inf is NaN, not 0).

Also examples of sorting objects by key.

@peirix 2009-06-30 10:49:01

Nice. But is there really no out-of-the-box way to get a numerical sort from javascript?

@Jack Franzen 2013-10-21 01:22:39

ahah this is out of the box! But if you're really impractical you can bind functions to the array class class at the very beginning of your javascript: // Array.prototype.sortNormal = function(){return this.sort(function(a,b){return a - b})} // Now calling .sortNormal() on any array will sort it numerically

@Krishna Shetty 2014-11-27 16:39:04

I have a requirement that it should not change the position of an array element when a = b. But above code changes array elements positions even though their values are same. Is there any workaround? Thanks

@QuentinUK 2015-02-23 22:24:17

Is there a need to convert the parameters to numbers?

@Luca Davanzo 2015-04-02 13:46:47

Why a-b and not a>b. I suggest the last one in order to avoid operation machine errors

@Iván Pérez 2015-09-28 10:21:21

@Velthune The compare function should return -1, 0 or +1. a>b will only return true or false.

@Константин Ван 2015-12-28 09:37:28

The compare function can return all the numeric value. The document: Array.prototype.sort

@Константин Ван 2015-12-28 09:41:21

This code can be shortened using an Arrow Function. numberArray.sort((a, b) => (a - b)); Yay! I think this is close to the out-of-the-box way. Note: check if your JS engine supports Arrow Functions.

@Peter Raeves 2016-07-06 11:00:53

Javascript did not bother to implement number sort? What is the reasoning behind this?

@bambery 2016-12-02 04:49:24

@K._ - I disagree that this is close to out of box way - you are using a side effect of the arrow syntax to cut out the words "function" and "return", but are not actually using the arrow function's true purpose of passing "this". I would strongly discourage others from using an arrow function here, as it implies there is some "this" context passing happening, but there isn't. Confusing for other developers to read your code, just to save a few chars.

@Alexander Chandra 2017-03-16 05:00:16

help me on the logic please?

@John Weisz 2017-04-28 13:55:04

@K._ -- You don't actually need the parentheses: .sort((a, b) => a - b) -- so it's even shorter.

@Black 2018-02-12 20:52:34

I don't understand why this works? Why even a - b and not a < b ?

@Eugene Kim 2018-05-25 20:01:21

@Black you should read the Array.prototype.sort() documentation page: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… You pass in a compare function to sort() that should return a value that's greater than zero, less than zero, or zero.

@Eugene Kim 2018-05-27 06:41:13

@Black It's simply what sort()'s compare function expects. Have you read the linked documentation? When sort() runs, it accounts for three cases and a boolean expression doesn't suffice. When determining the order of two objects a and b, sort() determines that: (1) a comes before b, (2) b comes before a, or (3) a and b should be left in the order they came in with respect to each other but sorted with respect to the other elements in the array. Having the comparator function return a number that's > 0, 0 or < 0 maps to the described scenarios nicely.

@Thomas Lobker 2018-06-08 21:55:16

You can make a true numeric sort by using parseInt() around the inputs. This way it will also work with numeric filenames for example: numArray.sort((a, b) => parseInt(a) - parseInt(b));

@vikramvi 2019-06-06 05:31:24

can you please clarify meaning of a-b and b-a to achieve ascending or descending order ?

@Marks Polakovs 2019-07-22 11:45:01

@vikramvi sort() expects a negative number if b should go after a in the order, or a positive number if a should go after b. a-b is negative when b is bigger than a and should go after a, and positive when a is bigger than b and should go after. Using b-a reverses it - now it's negative when a is bigger than b and should go after a. Example: [1,9]: 1-9 = -8, so 9 should go after 1 in ascending order - conversely, 9-1 is 8, so 1 should go after 9 in descending order.

@Error404 2019-06-14 23:49:59

This is the already proposed and accepted solution as a method on the Array prototype:

Array.prototype.sortNumeric = function () {
    return this.sort((a, b) => a - b);
};
Array.prototype.sortNumericDesc = function () {
    return this.sort((a, b) => b - a);
};

@Vardaman PK 2019-05-21 16:55:31

var numArray = [140000, 104, 99];
numArray = numArray.sort((a,b) => a-b);
alert(numArray)

@Simply Ged 2019-05-22 04:47:50

Welcome to StackOverflow. Your answer is identical to the accepted answer. Can you add any explanation to your answer to say why this should be preferred over the accepted answer?

@leet101 2019-01-26 07:58:29

The function 'numerically' below serves the purpose of sorting array of numbers numerically in many cases when provided as a callback function:

function numerically(a, b){
    return a-b;
}

array.sort(numerically); 

But in some rare instances, where array contains very large and negative numbers, an overflow error can occur as the result of a-b gets smaller than the smallest number that JavaScript can cope with.

So a better way of writing numerically function is as follows:

function numerically(a, b){
   if(a < b){
      return -1;
   } else if(a > b){
      return 1;
   } else {
      return 0;
   }
}

@Peter Cordes 2019-11-20 04:49:56

JavaScript numbers are floating-point. IEEE754 defines overflow and underflow rules, including overflow to +-Infinity, and underflow to subnormal or +-0.0. I don't think subtraction of two numbers can underflow to +-0.0 even if they're both large and nearby equal. The difference between two doubles is always representable as another non-zero double (unless it overflows, like DBL_MIN - DBL_MAX) but underflow isn't possible. Catastrophic cancellation makes the result imprecise, losing most of its "significant digits", but a-b will always be non-zero and have the right sign for a!=b.

@dy_ 2018-11-17 21:01:29

I am surprised why everyone recommends to pass a comparator funciton to sort(), that makes sorting really slow!

To sort numbers, just create any TypedArray:

var numArray = new Uint32Array([140000, 104, 99]);
numArray = numArray.sort();
alert(numArray)

@DragonSpit 2019-08-10 02:26:08

Using a TypedArray speeds up sort by about 5X. If you want to go even faster hpc-algorithms npm package implements Radix Sort and Counting Sort that several answers here suggest.

@Chait 2018-11-16 18:17:48

In the new ES6 world its much easier to do a sort

numArray.sort((a,b) => a-b);

Thats all you need :)

@Ali Khosro 2018-10-11 22:40:35

to handle undefined, null, and NaN: Null behaves like 0, NaN and undefined goes to end.

array = [3, 5, -1, 1, NaN, 6, undefined, 2, null]
array.sort((a,b) => isNaN(a) || a-b)
// [-1, null, 1, 2, 3, 5, 6, NaN, undefined]

@Black 2018-05-26 07:07:54

The reason why the sort function behaves so weird

From the documentation:

[...] the array is sorted according to each character's Unicode code point value, according to the string conversion of each element.

If you print the unicode point values of the array then it will get clear.

console.log("140000".charCodeAt(0));
console.log("104".charCodeAt(0));
console.log("99".charCodeAt(0));

//Note that we only look at the first index of the number "charCodeAt(  0  )"

This returns: "49, 49, 57".

49 (unicode value of first number at 140000)
49 (unicode value of first number at 104)
57 (unicode value of first number at 99)

Now, because 140000 and 104 returned the same values (49) it cuts the first index and checks again:

console.log("40000".charCodeAt(0));
console.log("04".charCodeAt(0));

//Note that we only look at the first index of the number "charCodeAt(  0  )"

52 (unicode value of first number at 40000)
40 (unicode value of first number at 04)

If we sort this, then we will get:

40 (unicode value of first number at 04)
52 (unicode value of first number at 40000)

so 104 comes before 140000.

So the final result will be:

var numArray = [140000, 104, 99];
numArray = numArray.sort();
console.log(numArray)

104, 140000, 99

Conclusion:

sort() does sorting by only looking at the first index of the numbers. sort() does not care if a whole number is bigger than another, it compares the value of the unicode of the digits, and if there are two equal unicode values, then it checks if there is a next digit and compares it as well.

To sort correctly, you have to pass a compare function to sort() like explained here.

@Black 2019-05-31 09:19:50

Hint: This is only my explanation, I did not actually looked up the code. So don't fully trust this answer.

@Commercial Suicide 2016-06-26 18:34:50

The question has already been answered, the shortest way is to use sort() method. But if you're searching for more ways to sort your array of numbers, and you also love cycles, check the following

Insertion sort

Ascending:

var numArray = [140000, 104, 99];
for (var i = 0; i < numArray.length; i++) {
    var target = numArray[i];
    for (var j = i - 1; j >= 0 && (numArray[j] > target); j--) {
        numArray[j+1] = numArray[j];
    }
    numArray[j+1] = target
}
console.log(numArray);

Descending:

var numArray = [140000, 104, 99];
for (var i = 0; i < numArray.length; i++) {
    var target = numArray[i];
    for (var j = i - 1; j >= 0 && (numArray[j] < target); j--) {
        numArray[j+1] = numArray[j];
    }
    numArray[j+1] = target
}
console.log(numArray);

Selection sort:

Ascending:

var numArray = [140000, 104, 99];
for (var i = 0; i < numArray.length - 1; i++) {
    var min = i;
    for (var j = i + 1; j < numArray.length; j++) {
        if (numArray[j] < numArray[min]) {
            min = j;
        }
    }
    if (min != i) {
        var target = numArray[i];
        numArray[i] = numArray[min];
        numArray[min] = target;
    }
}
console.log(numArray);

Descending:

var numArray = [140000, 104, 99];
for (var i = 0; i < numArray.length - 1; i++) {
    var min = i;
    for (var j = i + 1; j < numArray.length; j++) {
        if (numArray[j] > numArray[min]) {
            min = j;
        }
    }
    if (min != i) {
        var target = numArray[i];
        numArray[i] = numArray[min];
        numArray[min] = target;
    }
}
console.log(numArray);

Have fun

@Peter Cordes 2019-11-20 04:43:29

Are any of these actually faster for tiny arrays than using sort() on a TypedArray like this answer suggests. Certainly they won't be faster for medium to large arrays because these are O(n^2) algorithms.

@user7125929 2018-02-07 10:58:03

Try this code as below

var a = [5, 17, 29, 48, 64, 21];
function sortA(arr) {
return arr.sort(function(a, b) {
return a - b;
})
;} 
alert(sortA(a));

@user7125929 2018-02-12 13:03:31

is it not true ?

@Umesh 2018-02-07 11:04:38

For a normal array of elements values only:

function sortArrayOfElements(arrayToSort) {
    function compareElements(a, b) {
        if (a < b)
            return -1;
        if (a > b)
            return 1;
        return 0;
    }

    return arrayToSort.sort(compareElements);
}

e.g. 1:
var array1 = [1,2,545,676,64,2,24]
**output : [1, 2, 2, 24, 64, 545, 676]**

var array2 = ["v","a",545,676,64,2,"24"]
**output: ["a", "v", 2, "24", 64, 545, 676]**

For an array of objects:

function sortArrayOfObjects(arrayToSort, key) {
    function compareObjects(a, b) {
        if (a[key] < b[key])
            return -1;
        if (a[key] > b[key])
            return 1;
        return 0;
    }

    return arrayToSort.sort(compareObjects);
}

e.g. 1: var array1= [{"name": "User4", "value": 4},{"name": "User3", "value": 3},{"name": "User2", "value": 2}]

**output : [{"name": "User2", "value": 2},{"name": "User3", "value": 3},{"name": "User4", "value": 4}]**

@Merbin Joe 2016-03-02 07:53:10

Array.prototype.sort() is the go to method for sorting arrays, but there are a couple of issues we need to be aware of.

The sorting order is by default lexicographic and not numeric regardless of the types of values in the array. Even if the array is all numbers, all values will be converted to string and sorted lexicographically.

So should we need to customize the sort() and reverse() method like below.

Referred URL

For sorting numbers inside the array

numArray.sort(function(a, b)
{
    return a - b;
});

For reversing numbers inside the array

numArray.sort(function(a, b)
{
    return b - a;
});

Referred URL

@jjjjs 2016-02-03 20:07:51

This answer is equivalent to some of the existing answers, but ECMAScript 6 arrow functions provide a much more compact syntax that allows us to define an inline sort function without sacrificing readability:

numArray = numArray.sort((a, b) => a - b);

It is supported in most browsers today.

@Sphinxxx 2016-02-03 20:33:02

Sadly not that great browser support yet: caniuse.com/#feat=arrow-functions

@Tristan 2016-02-10 08:27:28

"without sacrificing readability". This is subjective. With some simple integers it is readable. When working with complexer objects and you want to sort on a property, not so much.

@jjjjs 2016-02-12 16:28:54

@Tristan, sorting on a property of an object can still be done pretty cleanly using this syntax. If the property of the object you want to sort on is a number you can do: objArray=objArray.sort((a,b)=>a.numProperty - b.numProperty); and if the property is a string you can do: objArray=objArray.sort((a,b)=>a.strProperty.localeCompare(b.‌​strProperty))‌​; That having been said, this question specifically asks about sorting an array of integers

@Sunny S.M 2015-11-17 05:48:57

Try this code:

HTML:

<div id="demo"></div>

JavaScript code:

<script>
    (function(){
        var points = [40, 100, 1, 5, 25, 10];
        document.getElementById("demo").innerHTML = points;
        points.sort(function(a, b){return a-b});
        document.getElementById("demo").innerHTML = points;
    })();
</script>

@firestoke 2014-06-27 06:10:51

Here is my sort array function in the utils library:

sortArray: function(array) {
    array.sort(function(a, b) {
        return a > b;
    });
},

# Let's test a string array
var arr = ['bbc', 'chrome', 'aux', 'ext', 'dog'];
utils.sortArray(arr);
console.log(arr);
>>> ["aux", "bbc", "chrome", "dog", "ext", remove: function]

# Let's test a number array
var arr = [55, 22, 1425, 12, 78];
utils.sortArray(arr);
console.log(arr);
>>> [12, 22, 55, 78, 1425, remove: function]

@jperelli 2016-11-17 20:57:29

This is plain wrong! sort function needs to return negative, 0 or positive numbers, not true or false.

@ecc521 2019-09-17 00:12:11

As @jperelli has mentioned, the sort function needs a number, not a boolean, to be returned (and given how there are 3 possible states, equal, above, and below, this is necessary to have a stable sort). As your answer is stated, it does not work. a-b should be used instead. (You can get fancy and do a Number(a>b)-0.5, however that is still not a stable sort).

@user130076 2009-06-30 10:48:26

In JavaScript the sort() method's default behaviour is to sort values in an array alphabetically.

To sort by number you have to define a numeric sort function (which is very easy):

...
function sortNumber(a, b)
{
  return a - b;
}

numArray = numArray.sort(sortNumber);

@MarzSocks 2014-02-06 06:07:36

Just building on all of the above answers, they can also be done in one line like this:

var numArray = [140000, 104, 99];

// ES5
numArray = numArray.sort(function (a, b) {  return a - b;  });

// ES2015
numArray = numArray.sort((a, b) => a - b);

//outputs: 99, 104, 140000

@bodyflex 2015-12-04 12:26:07

I think you mean in one expression.

@00500005 2016-05-17 16:18:19

@bodyflex Fixed: var arr = [140000, 104, 99].sort(function(a,b) { return a-b; });. Or more compact, in ES6 let arr = [140000, 104, 99].sort((a,b) => a-b);

@bambery 2016-12-02 05:03:04

As I said in a comment above, arrow functions are a bad fit here and I would discourage anyone from using them this way. You are using a side effect of the arrow syntax to cut out the words function and return, but are not actually using the arrow function's true purpose of passing this. This code implies there is some this context passing happening, but there isn't. Confusing for other developers to read your code, just to save a few chars. Don't depend on side effects - code with purpose!

@Ted Morin 2017-02-21 20:02:28

@bambery I don't think that you need to use an arrow function exclusively for context changes…

@cuth 2017-04-04 22:07:05

@bambery, you actually misunderstand what the arrow function is doing. You think that it somehow passes this into the function but that isn't true. It actually neglects to create a this and the arguments variable which usually overwrite the parent variables. The only reason you can use this inside an arrow function is the lexical scoping.

@Kip 2019-10-25 19:32:38

@bambery that didn't age well... three years later and modern javascript development uses arrow functions almost exclusively. :)

@SpYk3HH 2014-12-07 19:02:33

Update! Scroll to bottom of answer for smartSort prop additive that gives even more fun!
Sorts arrays of anything!

My personal favorite form of this function allows for a param for Ascending, or Descending:

function intArraySort(c, a) {
    function d(a, b) { return b - a; }
    "string" == typeof a && a.toLowerCase();
    switch (a) {
        default: return c.sort(function(a, b) { return a - b; });
        case 1:
                case "d":
                case "dc":
                case "desc":
                return c.sort(d)
    }
};

Usage as simple as:

var ara = function getArray() {
        var a = Math.floor(Math.random()*50)+1, b = [];
        for (i=0;i<=a;i++) b.push(Math.floor(Math.random()*50)+1);
        return b;
    }();

//    Ascending
intArraySort(ara);
console.log(ara);

//    Descending
intArraySort(ara, 1);
console.log(ara);

//    Ascending
intArraySort(ara, 'a');
console.log(ara);

//    Descending
intArraySort(ara, 'dc');
console.log(ara);

//    Ascending
intArraySort(ara, 'asc');
console.log(ara);

jsFiddle


Or Code Snippet Example Here!

function intArraySort(c, a) {
	function d(a, b) { return b - a }
	"string" == typeof a && a.toLowerCase();
	switch (a) {
		default: return c.sort(function(a, b) { return a - b });
		case 1:
		case "d":
		case "dc":
		case "desc":
		return c.sort(d)
	}
};

function tableExample() {
	var d = function() {
			var a = Math.floor(50 * Math.random()) + 1,
				b = [];
			for (i = 0; i <= a; i++) b.push(Math.floor(50 * Math.random()) + 1);
			return b
		},
		a = function(a) {
			var b = $("<tr/>"),
				c = $("<th/>").prependTo(b);
			$("<td/>", {
				text: intArraySort(d(), a).join(", ")
			}).appendTo(b);
			switch (a) {
				case 1:
				case "d":
				case "dc":
				case "desc":
					c.addClass("desc").text("Descending");
					break;
				default:
					c.addClass("asc").text("Ascending")
			}
			return b
		};
	return $("tbody").empty().append(a(), a(1), a(), a(1), a(), a(1), a(), a(1), a(), a(1), a(), a(1))
};

tableExample();
table { border-collapse: collapse; }
th, td { border: 1px solid; padding: .25em .5em; vertical-align: top; }
.asc { color: red; }
.desc { color: blue }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<table><tbody></tbody></table>


.smartSort('asc' | 'desc')

Now have even more fun with a sorting method that sorts an array full of multiple items! Doesn't currently cover "associative" (aka, string keys), but it does cover about every type of value! Not only will it sort the multiple values asc or desc accordingly, but it will also maintain constant "position" of "groups" of values. In other words; ints are always first, then come strings, then arrays (yes, i'm making this multidimensional!), then Objects (unfiltered, element, date), & finally undefineds and nulls!

"Why?" you ask. Why not!

Now comes in 2 flavors! The first of which requires newer browsers as it uses Object.defineProperty to add the method to the Array.protoype Object. This allows for ease of natural use, such as: myArray.smartSort('a'). If you need to implement for older browsers, or you simply don't like modifying native Objects, scroll down to Method Only version.

/* begin */
/* KEY NOTE! Requires EcmaScript 5.1 (not compatible with older browsers) */
;;(function(){if(Object.defineProperty&&!Array.prototype.smartSort){var h=function(a,b){if(null==a||void 0==a)return 1;if(null==b||void 0==b)return-1;var c=typeof a,e=c+typeof b;if(/^numbernumber$/ig.test(e))return a-b;if(/^stringstring$/ig.test(e))return a>b;if(/(string|number){2}/ig.test(e))return/string/i.test(c)?1:-1;if(/number/ig.test(e)&&/object/ig.test(e)||/string/ig.test(e)&&/object/ig.test(e))return/object/i.test(c)?1:-1;if(/^objectobject$/ig.test(e)){a instanceof Array&&a.smartSort("a");b instanceof Array&&b.smartSort("a");if(a instanceof Date&&b instanceof Date)return a-b;if(a instanceof Array&&b instanceof Array){var e=Object.keys(a),g=Object.keys(b),e=e.concat(g).smartSort("a"),d;for(d in e)if(c=e[d],a[c]!=b[c])return d=[a[c],b[c]].smartSort("a"),a[c]==d[0]?-1:1;var f=[a[Object.keys(a)[0]],b[Object.keys(b)[0]]].smartSort("a");return a[Object.keys(a)[0]]==f[0]?-1:1}if(a instanceof Element&&b instanceof Element){if(a.tagName==b.tagName)return e=[a.id,b.id].smartSort("a"),a.id==e[0]?1:-1;e=[a.tagName, b.tagName].smartSort("a");return a.tagName==e[0]?1:-1}if(a instanceof Date||b instanceof Date)return a instanceof Date?1:-1;if(a instanceof Array||b instanceof Array)return a instanceof Array?-1:1;e=Object.keys(a);g=Object.keys(b);e.concat(g).smartSort("a");for(c=0;20>c;c++){d=e[c];f=g[c];if(a.hasOwnProperty(d)&&b.hasOwnProperty(f)){if(a[d]instanceof Element&&b[f]instanceof Element){if(a[d].tagName==b[f].tagName)return c=[a[d].id,b[f].id].smartSort("a"),a[d].id==c[0]?-1:1;c=[a[d].tagName,b[f].tagName].smartSort("d"); return a[d].tagName==c[0]?1:-1}if(a[d]instanceof Element||b[f]instanceof Element)return a[d]instanceof Element?1:-1;if(a[d]!=b[f])return c=[a[d],b[f]].smartSort("a"),a[d]==c[0]?-1:1}if(a.hasOwnProperty(d)&&a[d]instanceof Element)return 1;if(b.hasOwnProperty(f)&&b[f]instanceof Element||!a.hasOwnProperty(d))return-1;if(!b.hasOwnProperty(d))return 1}c=[a[Object.keys(a)[0]],b[Object.keys(b)[0]]].smartSort("d");return a[Object.keys(a)[0]]==c[0]?-1:1}g=[a,b].sort();return g[0]>g[1]},k=function(a,b){if(null== a||void 0==a)return 1;if(null==b||void 0==b)return-1;var c=typeof a,e=c+typeof b;if(/^numbernumber$/ig.test(e))return b-a;if(/^stringstring$/ig.test(e))return b>a;if(/(string|number){2}/ig.test(e))return/string/i.test(c)?1:-1;if(/number/ig.test(e)&&/object/ig.test(e)||/string/ig.test(e)&&/object/ig.test(e))return/object/i.test(c)?1:-1;if(/^objectobject$/ig.test(e)){a instanceof Array&&a.smartSort("d");b instanceof Array&&b.smartSort("d");if(a instanceof Date&&b instanceof Date)return b-a;if(a instanceof Array&&b instanceof Array){var e=Object.keys(a),g=Object.keys(b),e=e.concat(g).smartSort("a"),d;for(d in e)if(c=e[d],a[c]!=b[c])return d=[a[c],b[c]].smartSort("d"),a[c]==d[0]?-1:1;var f=[a[Object.keys(a)[0]],b[Object.keys(b)[0]]].smartSort("d");return a[Object.keys(a)[0]]==f[0]?-1:1}if(a instanceof Element&&b instanceof Element){if(a.tagName==b.tagName)return e=[a.id,b.id].smartSort("d"),a.id==e[0]?-1:1;e=[a.tagName,b.tagName].smartSort("d");return a.tagName==e[0]?-1:1}if(a instanceof Date||b instanceof Date)return a instanceof Date?1:-1;if(a instanceof Array||b instanceof Array)return a instanceof Array?-1:1;e=Object.keys(a);g=Object.keys(b);e.concat(g).smartSort("a");for(c=0;20>c;c++){d=e[c];f=g[c];if(a.hasOwnProperty(d)&&b.hasOwnProperty(f)){if(a[d]instanceof Element&&b[f]instanceof Element){if(a[d].tagName==b[f].tagName)return c=[a[d].id,b[f].id].smartSort("d"),a[d].id==c[0]?-1:1;c=[a[d].tagName,b[f].tagName].smartSort("d");return a[d].tagName==c[0]?-1:1}if(a[d]instanceof Element||b[f]instanceof Element)return a[d]instanceof Element?1:-1;if(a[d]!=b[f])return c=[a[d],b[f]].smartSort("d"),a[d]==c[0]?-1:1}if(a.hasOwnProperty(d)&&a[d]instanceof Element)return 1;if(b.hasOwnProperty(f)&&b[f]instanceof Element)return-1;if(!a.hasOwnProperty(d))return 1;if(!b.hasOwnProperty(d))return-1}c=[a[Object.keys(a)[0]],b[Object.keys(b)[0]]].smartSort("d");return a[Object.keys(a)[0]]==c[0]?-1:1}g=[a,b].sort();return g[0]<g[1]};Object.defineProperty(Array.prototype,"smartSort",{value:function(){return arguments&& (!arguments.length||1==arguments.length&&/^a([sc]{2})?$|^d([esc]{3})?$/i.test(arguments[0]))?this.sort(!arguments.length||/^a([sc]{2})?$/i.test(arguments[0])?h:k):this.sort()}})}})();
/* end */

jsFiddle Array.prototype.smartSort('asc|desc')


Use is simple! First make some crazy array like:

window.z = [ 'one', undefined, $('<span />'), 'two', null, 2, $('<div />', { id: 'Thing' }), $('<div />'), 4, $('<header />') ];
z.push(new Date('1/01/2011'));
z.push('three');
z.push(undefined);
z.push([ 'one', 'three', 'four' ]);
z.push([ 'one', 'three', 'five' ]);
z.push({ a: 'a', b: 'b' });
z.push({ name: 'bob', value: 'bill' });
z.push(new Date());
z.push({ john: 'jill', jack: 'june' });
z.push([ 'abc', 'def', [ 'abc', 'def', 'cba' ], [ 'cba', 'def', 'bca' ], 'cba' ]);
z.push([ 'cba', 'def', 'bca' ]);
z.push({ a: 'a', b: 'b', c: 'c' });
z.push({ a: 'a', b: 'b', c: 'd' });

Then simply sort it!

z.smartSort('asc'); // Ascending
z.smartSort('desc'); // Descending

Method Only

Same as the preceding, except as just a simple method!

/* begin */
/* KEY NOTE! Method `smartSort` is appended to native `window` for global use. If you'd prefer a more local scope, simple change `window.smartSort` to `var smartSort` and place inside your class/method */
window.smartSort=function(){if(arguments){var a,b,c;for(c in arguments)arguments[c]instanceof Array&&(a=arguments[c],void 0==b&&(b="a")),"string"==typeof arguments[c]&&(b=/^a([sc]{2})?$/i.test(arguments[c])?"a":"d");if(a instanceof Array)return a.sort("a"==b?smartSort.asc:smartSort.desc)}return this.sort()};smartSort.asc=function(a,b){if(null==a||void 0==a)return 1;if(null==b||void 0==b)return-1;var c=typeof a,e=c+typeof b;if(/^numbernumber$/ig.test(e))return a-b;if(/^stringstring$/ig.test(e))return a> b;if(/(string|number){2}/ig.test(e))return/string/i.test(c)?1:-1;if(/number/ig.test(e)&&/object/ig.test(e)||/string/ig.test(e)&&/object/ig.test(e))return/object/i.test(c)?1:-1;if(/^objectobject$/ig.test(e)){a instanceof Array&&a.sort(smartSort.asc);b instanceof Array&&b.sort(smartSort.asc);if(a instanceof Date&&b instanceof Date)return a-b;if(a instanceof Array&&b instanceof Array){var e=Object.keys(a),g=Object.keys(b),e=smartSort(e.concat(g),"a"),d;for(d in e)if(c=e[d],a[c]!=b[c])return d=smartSort([a[c], b[c]],"a"),a[c]==d[0]?-1:1;var f=smartSort([a[Object.keys(a)[0]],b[Object.keys(b)[0]]],"a");return a[Object.keys(a)[0]]==f[0]?-1:1}if(a instanceof Element&&b instanceof Element){if(a.tagName==b.tagName)return e=smartSort([a.id,b.id],"a"),a.id==e[0]?1:-1;e=smartSort([a.tagName,b.tagName],"a");return a.tagName==e[0]?1:-1}if(a instanceof Date||b instanceof Date)return a instanceof Date?1:-1;if(a instanceof Array||b instanceof Array)return a instanceof Array?-1:1;e=Object.keys(a);g=Object.keys(b);smartSort(e.concat(g), "a");for(c=0;20>c;c++){d=e[c];f=g[c];if(a.hasOwnProperty(d)&&b.hasOwnProperty(f)){if(a[d]instanceof Element&&b[f]instanceof Element){if(a[d].tagName==b[f].tagName)return c=smartSort([a[d].id,b[f].id],"a"),a[d].id==c[0]?-1:1;c=smartSort([a[d].tagName,b[f].tagName],"a");return a[d].tagName==c[0]?-1:1}if(a[d]instanceof Element||b[f]instanceof Element)return a[d]instanceof Element?1:-1;if(a[d]!=b[f])return c=smartSort([a[d],b[f]],"a"),a[d]==c[0]?-1:1}if(a.hasOwnProperty(d)&&a[d]instanceof Element)return 1; if(b.hasOwnProperty(f)&&b[f]instanceof Element||!a.hasOwnProperty(d))return-1;if(!b.hasOwnProperty(d))return 1}c=smartSort([a[Object.keys(a)[0]],b[Object.keys(b)[0]]],"a");return a[Object.keys(a)[0]]==c[0]?1:-1}g=[a,b].sort();return g[0]>g[1]};smartSort.desc=function(a,b){if(null==a||void 0==a)return 1;if(null==b||void 0==b)return-1;var c=typeof a,e=c+typeof b;if(/^numbernumber$/ig.test(e))return b-a;if(/^stringstring$/ig.test(e))return b>a;if(/(string|number){2}/ig.test(e))return/string/i.test(c)? 1:-1;if(/number/ig.test(e)&&/object/ig.test(e)||/string/ig.test(e)&&/object/ig.test(e))return/object/i.test(c)?1:-1;if(/^objectobject$/ig.test(e)){a instanceof Array&&a.sort(smartSort.desc);b instanceof Array&&b.sort(smartSort.desc);if(a instanceof Date&&b instanceof Date)return b-a;if(a instanceof Array&&b instanceof Array){var e=Object.keys(a),g=Object.keys(b),e=smartSort(e.concat(g),"a"),d;for(d in e)if(c=e[d],a[c]!=b[c])return d=smartSort([a[c],b[c]],"d"),a[c]==d[0]?-1:1;var f=smartSort([a[Object.keys(a)[0]], b[Object.keys(b)[0]]],"d");return a[Object.keys(a)[0]]==f[0]?-1:1}if(a instanceof Element&&b instanceof Element){if(a.tagName==b.tagName)return e=smartSort([a.id,b.id],"d"),a.id==e[0]?-1:1;e=smartSort([a.tagName,b.tagName],"d");return a.tagName==e[0]?-1:1}if(a instanceof Date||b instanceof Date)return a instanceof Date?1:-1;if(a instanceof Array||b instanceof Array)return a instanceof Array?-1:1;e=Object.keys(a);g=Object.keys(b);smartSort(e.concat(g),"a");for(c=0;20>c;c++){d=e[c];f=g[c];if(a.hasOwnProperty(d)&& b.hasOwnProperty(f)){if(a[d]instanceof Element&&b[f]instanceof Element){if(a[d].tagName==b[f].tagName)return c=smartSort([a[d].id,b[f].id],"d"),a[d].id==c[0]?-1:1;c=smartSort([a[d].tagName,b[f].tagName],"d");return a[d].tagName==c[0]?-1:1}if(a[d]instanceof Element||b[f]instanceof Element)return a[d]instanceof Element?1:-1;if(a[d]!=b[f])return c=smartSort([a[d],b[f]],"d"),a[d]==c[0]?-1:1}if(a.hasOwnProperty(d)&&a[d]instanceof Element)return 1;if(b.hasOwnProperty(f)&&b[f]instanceof Element)return-1; if(!a.hasOwnProperty(d))return 1;if(!b.hasOwnProperty(d))return-1}c=smartSort([a[Object.keys(a)[0]],b[Object.keys(b)[0]]],"d");return a[Object.keys(a)[0]]==c[0]?-1:1}g=[a,b].sort();return g[0]<g[1]}
/* end */

Use:

z = smartSort(z, 'asc'); // Ascending
z = smartSort(z, 'desc'); // Descending

jsFiddle Method smartSort(Array, "asc|desc")

@user3587638 2014-11-18 19:41:00

I agree with aks, however instead of using

return a - b;

You should use

return a > b ? 1 : a < b ? -1 : 0;

@stefannew 2015-01-16 17:05:37

Can you explain why anyone should use your more unreadable ternary operation? As far as I can tell it would have the same result.

@Maarten00 2015-02-03 18:57:07

This answer also takes equal values into consideration and leaves them in the same place.

@Bryan Rayner 2015-02-25 18:51:31

And a - b doesn't?

@Celdor 2015-08-07 08:12:39

well, even though this answer doesn't contribute anything esle to the topic it doesn't deserve to get -1. All in all it is a valid answer, redendant but valid.

@Don Hatch 2015-12-08 00:21:50

"return a-b" may be adequate for the particular case of this question (javascript, and all input items known to be ints), but personally I prefer the ternary form because it's more canonical-- it works in more cases, in more programming languages, with more data types. E.g. in C, a-b can overflow, leading to the sort endless looping, corrupting memory, crashing, etc. That said, even the ternary form isn't going to work sanely if there are NaNs or mixed types involved.

@vriesdemichael 2016-11-18 11:58:21

The > and < still compare a and b as strings.

@Nate 2016-12-21 18:00:13

Maybe a minor quibble, but: In javascript, there's only one numeric type; everything is a float.

@7vujy0f0hy 2017-04-02 13:09:21

return +(a > b) || -(a < b);

@Artyer 2017-04-15 20:54:51

@stefannew There is one case where this answer returns the correct evaluation for numbers where a - b doesnt. Where a = b = -Infinity, a - b = NaN, but the ternary returns 0. But this doesn't seem to affect the sort, it still does it perfectly. (a > b) - (a < b) is a shorter version that is equivalent to this ternary.

@Roman Starkov 2017-11-09 22:42:23

@vriesdemichael no they don't?

@wOxxOm 2018-10-17 19:33:00

@RomanStarkov the point was that neither a<b nor a>b coerces the string elements into numbers whereas a-b does.

@kevinji 2018-11-19 02:27:45

@vriesdemichael @wOxxom I don't think a or b are strings in the sort fn; e.g. [101, 3, -15].sort((a, b) => { console.log(typeof a); return a - b }) outputs number some number of times (depending on the browser) and sorts the values correctly.

@Paul Dixon 2009-06-30 10:47:55

array.sort does a lexicographic sort by default, for a numeric sort, provide your own function. Here's a simple example:

function compareNumbers(a, b)
{
    return a - b;
}

numArray.sort(compareNumbers);

Also note that sort works "in place", there's no need for the assignment.

@vikramvi 2019-07-08 06:58:38

I didn't understand above code, how does "return a - b" does the ascending sorting ?

@Paul Dixon 2019-07-08 14:01:31

if a < b, compareNumbers returns a negative number. If a > b, it will be positive. If equal, it returns 0.

Related Questions

Sponsored Content

86 Answered Questions

[SOLVED] How do JavaScript closures work?

89 Answered Questions

[SOLVED] How do I remove a particular element from an array in JavaScript?

  • 2011-04-23 22:17:18
  • Walker
  • 6162068 View
  • 7684 Score
  • 89 Answer
  • Tags:   javascript arrays

56 Answered Questions

[SOLVED] How do I check if an element is hidden in jQuery?

34 Answered Questions

[SOLVED] How do I sort a dictionary by value?

43 Answered Questions

[SOLVED] Sort array of objects by string property value

47 Answered Questions

3 Answered Questions

33 Answered Questions

[SOLVED] For-each over an array in JavaScript?

58 Answered Questions

[SOLVED] How do I redirect to another webpage?

30 Answered Questions

[SOLVED] How to append something to an array?

Sponsored Content