47

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"
    }
]
Community
  • 1
  • 1
Dennis Martinez
  • 6,344
  • 11
  • 50
  • 67
  • 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 `id`s and `name`s are unique. It's equivalent to just sort by `name`. – Bill Oct 15 '12 at 16:41
  • Agreed - what exactly do you want the ordering semantics to be here? – Pointy Oct 15 '12 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](http://www.tutorialspoint.com/javascript/string_localecompare.htm) instead.) – Elliot Bonneville Oct 15 '12 at 16:43
  • https://stackoverflow.com/questions/1129216/sort-array-of-objects-by-string-property-value-in-javascript/50600956#50600956 – Harun Or Rashid Jul 03 '18 at 13:06
  • The title of the question is very search friendly. The example is flipped compared to what the title says. – OXiGEN Mar 25 '22 at 13:02

5 Answers5

97

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).

raina77ow
  • 103,633
  • 15
  • 192
  • 229
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);  
bhb
  • 2,476
  • 3
  • 17
  • 32
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.

Jeremy J Starcher
  • 23,369
  • 6
  • 54
  • 74
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;

BostonJohn
  • 2,631
  • 2
  • 26
  • 48
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.

David Hoerster
  • 28,421
  • 8
  • 67
  • 102