7

In Javascript, if I have an array of arrays, like the following:

X = [ [1,2,3,4],
      [1,1,2,3],
      [1,1,3],
      [1,4],
      [2,1,2],
      [2,2]
    ]

Javascript sorts my array, comparing first entry first, then second, and so on, so that X.sort() returns the following:

[ [1,1,2,3],
  [1,1,3],
  [1,2,3,4],
  [1,4],
  [2,1,2],
  [2,2]
]

Which is what I want. The problem is that the comparison operator for comparing the elements in the arrays is lexicographical, so [10,2] < [2,2], and, for example,

[[10,2],[1,1,3],[2,2]].sort() -> [[1,1,3],[10,2],[2,2]]

I need it to sort numerically, so that I get a sorted array of [[1,1,3],[2,2],[10,2]].

I tried using a comparison function of function(a,b){return (a-b) }, which would work for sorting an array of numbers, but this fails to properly sort my array, which makes sense (I think) because [10,2] - [1,1,3] yields NaN

How do I go about sorting an array of numeric arrays?

3
  • 5
    If you change the compare function to account for the fact that the arguments passed are arrays, it should work. jsfiddle.net/SYHr2
    – Rikonator
    Commented Mar 28, 2013 at 15:35
  • @Rikonator Great solution, you might want to post that as an answer, it seems to work
    – Ian
    Commented Mar 28, 2013 at 15:39
  • @Rikonator Fantastic! Gives me the sorting capability I need with a slim function that doesn't overwrite the natural .sort method. If you write it up as an answer I'll accept it.
    – ckersch
    Commented Mar 28, 2013 at 15:48

5 Answers 5

8

As I said in my comment, the sort function needs to account for the fact that it's receiving arrays as arguments and not plain values. So you need to handle them accordingly.

I suggest this;

var compFunc = function (a, b) {
    var len = a.length > b.length ? b.length : a.length;

    for(var i=0; i<len; ++i) {
        if(a[i] - b[i] !== 0)
            return a[i] - b[i];
    }

    return (a.length - b.length);
};

It first tries to look for differences in the common length of the two arrays. If the common length is exactly the same, then it sorts on the basis of array length. Here's a working fiddle.

2
  • 1
    var len = Math.min(a.length, b.length); Other than that, barring style, your function is exactly how I would have coded it. Thank you for not going with the "only one exit point from a function" madness!
    – ErikE
    Commented Mar 28, 2013 at 17:31
  • Is there a reason why a[i] - b[i] is computed twice? I'm wondering if there is some low level stuff going on that I don't understand where it is faster to compute twice than to reuse it as a local.
    – Adverbly
    Commented Oct 20, 2019 at 22:17
1

What you want is to run a natural sort. For your compare function, replace it with the script mentioned in this article

http://my.opera.com/GreyWyvern/blog/show.dml/1671288

1

When you do X.sort(), Javascript is comparing your individual arrays as strings. It's basically doing a.toString().localeCompare(b.toString()). This is not what you want.

a.toString() is usually the same as a.join(',')

What I would do is compare each element in the arrays by using a for loop.

Something like this:

X.sort(function(a,b){
    // Start off assuming values are equal
    var ret = 0;

    // Loop through a
    for(var a_i = 0, a_length = a.length; a_i < a_length; a_i++){
        // If b is shorter than a, it comes first
        if(typeof b[a_i] === 'undefined'){
            ret = 1;
            break;
        }
        // if the element in a and b are *not* the same, then we can sort
        else if(a[a_i] !== b[a_i]){
            ret = a[a_i] - b[a_i];
            break;
        }
    }

    return ret;
});
0

You need to sort and compare between the 2 arrays: http://jsfiddle.net/pXzB6/

var arr = [[10,2],[1,1,3],[2,2]];

arr.sort(function(a,b){
    for(var i=0;i<a.length;i++){
       var item_a = a[i];
       for(var j=0;j<b.length;b++){   
           var item_b = b[j];   
           if(item_a == item_b){
                 continue;
           }
           else{
               return item_a > item_b;
           }
       }
    }

    if(a.length == b.length){
       return 0;
    }
    else{
      return a.length > b.length;
    }
});

console.log(arr);
0

var points = [40, 100, 1, 5, 25, 10];

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

then the result is : 1,5,10,25,40,100

This is simplest way i think, it's worked.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.