66

I have an array that contains several arrays and I would like to order the arrays based on a certain string within those arrays.

var myArray = [
                [1, 'alfred', '...'],
                [23, 'berta', '...'],
                [2, 'zimmermann', '...'],
                [4, 'albert', '...'],
              ];

How can I sort it by the name so that albert comes first and zimmermann comes last?

I know how I would do it if I could use the integer for sorting but the string leaves me clueless.

Thank for your help! :)

1

6 Answers 6

105

This can be achieved by passing a supporting function as an argument to the Array.sort method call.

Something like this:

 function Comparator(a, b) {
   if (a[1] < b[1]) return -1;
   if (a[1] > b[1]) return 1;
   return 0;
 }

 var myArray = [
   [1, 'alfred', '...'],
   [23, 'berta', '...'],
   [2, 'zimmermann', '...'],
   [4, 'albert', '...'],
 ];

 myArray = myArray.sort(Comparator);
 console.log(myArray);

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks Martin, that is working nicely. However, I have problems with names that are lowercase, those are sorted differently from names that start with the same uppercase letter.
In that case, use the toUpperCase method of the strings (a[1].toUpperCase() and b[1].toUpperCase) in the Comparator method instead. That will make the sort case insensitive
OT, but in many languages (Perl, Ruby, PHP, etc) there is a "spaceship operator" which natively compares and returns -1, 0, or 1 (as per your Comparator method). At the rate ES copies ideas, I would expect it to land in Babel soon.
42

You can still use array.sort() with a custom function. Inside the function, simply compare the element that you want to use as your key. For you example, you could use:

myArray.sort(function(a, b) { 
    return a[1] > b[1] ? 1 : -1;
});

4 Comments

I think you forgot the return
This does not handle equal strings (i.e., it does not return either -1, 1, or 0. @Martin Milan's reply is a better one
@Aleadam In theory, you are correct. The comparator is not within the required specs. However, in practice, this works just well enough if you don't care about elements with equal keys being swapped during the sort algorithm. For large arrays, this solution may end up being slower - depending on the implementation of array.sort(). But I need to return 1 or -1, at least. Editing answer.
so if you need to leave elements in place if equal: return a[1] == b[1] ? 0 : (a[1] > b[1] ? 1 : -1);
15

There´s an easier way now:

myArray = myArray.sort(function(a, b) {
    return a[1].localeCompare(b[1]);
})

It is case insensitive too.

Source: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare

3 Comments

"cannot find function localeCompare in object"
your array elements must be strings, not objects
yeah, I've tried converting numbers to strings and still get messed up results. stackoverflow.com/questions/33004116/…
9

In ES6 one might do the relatively pithy:

myArray.sort(([a], [b]) => a.localeCompare(b))

or

myArray.sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0)

The helpful/modern bits being the => lambda operator, and the [X] argument destructuring.

Comments

7

Awesome! Compound sort on first element, second element and then third, all ascending in this example, would be

myArray=myArray.sort(function(a,b){
    retVal=0;
    if(a[0]!=b[0]) retVal=a[0]>b[0]?1:-1;
    else if(a[1]!=b[1]) retVal=a[1]>b[1]?1:-1;
    else if(a[2]!=b[2]) retVal=a[2]>b[2]?1:-1;
    return retVal
});

(multiple sort on more than one column)

3 Comments

can this be done dynamically based on array length
I haven't played with dynamic array length, but I'd head in direction of retVal=0; var lenA=a.length; var lenB=b.length; var toLen=Math.min(lenA,lenB); for(i=0;i<toLen;i++){if(a[i]!=b[i]) retVal=a[i]>b[i]?1:-1;} return retVal; (ps Sorry not to see for so long.)
This assumes the ordering of the elements of your arrays matches the hierarchy of comparing the elements. If you need to bounce comparisons around among the elements, I suppose you could try passing that order in as another argument.
0

Kept getting issues with the solutions posted here. For a simple sorter of simple strings inside an array, I used this:

arr = ["aaa","abc","aba"]
arr.sort((a, b) => a.localeCompare(b));
console.log(arr);
//['aaa','aba','abc']

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.