51

Possible Duplicate:
Sorting objects in an array by a field value in JavaScript

How can I sort an array of objects numerically (by id) then alphabetically (by name)?

The current way is providing invalid output.

This is the object i'm trying to sort through

var items = [
    {
        "id": 165,
        "name": "a"
    },
    {
        "id": 236,
        "name": "c"
    },
    {
        "id": 376,
        "name": "b"
    },
    {
        "id": 253,
        "name": "f"
    },
    {
        "id": 235,
        "name": "e"
    },
    {
        "id": 24,
        "name": "d"
    },
    {
        "id": 26,
        "name": "d"
    }
]

and the way i'm trying to sort

items.sort(function(a, b) {
    return (a.id - b.id);
}).sort(function(a, b) {
    return (a.name - b.name);
});

here is the jsfiddle.

http://jsfiddle.net/jh4xb/

EDIT: Sorry for the confusion, I've been so confused by this problem for a while.

What I'm trying to accomplish is to sort by the highest id first, and then sort alphabetically so in the end it should look like:

var items = [
    {
        "id": 376,
        "name": "b"
    },
    {
        "id": 253,
        "name": "f"
    },
    {
        "id": 236,
        "name": "c"
    },
    {
        "id": 235,
        "name": "e"
    },
    {
        "id": 165,
        "name": "a"
    },
    {
        "id": 26,
        "name": "d"
    },
    {
        "id": 24,
        "name": "d"
    }
]
5
  • 2
    You might need a better example of what you are trying to accomplish because in this example, sorting by id first doesn't make sense since all of the ids and names are unique. It's equivalent to just sort by name. Commented Oct 15, 2012 at 16:41
  • Agreed - what exactly do you want the ordering semantics to be here? Commented Oct 15, 2012 at 16:42
  • 2
    Not sure what you're hoping to achieve by sorting the list twice. And when you do return (a.name - b.name) you're attempting to subtract one string from another. Ain't gonna happen. (You probably want localeCompare instead.) Commented Oct 15, 2012 at 16:43
  • stackoverflow.com/questions/1129216/… Commented Jul 3, 2018 at 13:06
  • The title of the question is very search friendly. The example is flipped compared to what the title says. Commented Mar 25, 2022 at 13:02

5 Answers 5

105

I think it's better done just with...

items.sort(function(a, b) { 
  return a.id - b.id  ||  a.name.localeCompare(b.name);
});

The second sort will basically negate the first one, so you have to do it once. )

a.id - b.id || a.name.localeCompare(b.name) expression will first compare the ids; only if they are equal, it will compare the names (and return the result of this comparison).

If you need to reverse the ordering, swap the positions (b.id - a.id, etc.) - or just negate the whole thing:

items.sort(function(a, b) { 
  return - ( a.id - b.id  ||  a.name.localeCompare(b.name) );
});

Here's the JSFiddle (have to simplify the data a bit to show my point).

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

1 Comment

Just what I needed! Sorry I wasn't so clear but this is perfect! Thanks!
7

Create a general function to sort it anyway you want. Check the dynamicSort function below

var items = [
{
 "id": 165,
 "name": "a"},
{
 "id": 236,
 "name": "b"},
{
 "id": 376,
 "name": "c"},
{
 "id": 253,
 "name": "d"},
{
 "id": 235,
 "name": "e"},
{
  "id": 24,
  "name": "f"}
];

function dynamicSort(property) {
   return function(a, b) {
       return (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0;
   }
}

items.sort(dynamicSort('name')).sort(dynamicSort('id'));
console.log(items);
items.sort(dynamicSort('id')).sort(dynamicSort('name')); 
console.log(items);  

Comments

5

IF you mean that you wanted them sorted by id and if the id matches, you want them sorted by name then use this:

items.sort(function(a, b) {
    if (a.id !== b.id) {
        return a.id - b.id
    }
    if (a.name === b.name) {
      return 0;
    }
    return a.name > b.name ? 1 : -1;
});

Otherwise your question is unclear.

Comments

3

your problem is how you're sorting the letters.
a.name - b.name

isn't doing what you think. It's not evaluating them in lexigraphical order. replace it with

a.name < b.name ? -1 : 1;

2 Comments

Why does your code return 1 if the names are equal? It should return 0
you're right. Doing it this way does not guarantee that equal elements will retain their original ordering.
0

I'm not seeing any errors in Chrome, but it's not sorting correctly.

If I change your sort code to this:

var firstRun = items.sort(function(a, b) {
    return (a.id - b.id);
});
var secondRun = firstRun.sort(function(a, b) {
    return (a.name - b.name);
});

console.log(secondRun);​

I believe it's sorting correctly. Your example doesn't really need to do the second sort as each number (id) is different. But when I make b, d and e all have an ID of 235, it sorts fine.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.