2

I have an object like this from which I need to sort by id.

64: {id: "83", name: "(83) x"}
65: {id: "84", name: "(84) y"}
66: {id: "85", name: "(85) z"}
67: {id: "86", name: "(86) a"}
68: {id: "9", name: "(9) b"}

I have checked many examples and I have tried them all but nothing worked for me

I tried this one first:

obj.sort((a, b) => {
            return a.id > b.id;
        })

Then,

obj.sort((a,b) => (a.id > b.id) ? 1 : ((b.id > a.id) ? -1 : 0));

Can anybody please help?

user1687891
  • 794
  • 2
  • 14
  • 30
  • What is the current result of your sort? Also, you must subtract your values in a sort to actually sort them, so you should probably change them to numbers – Andria Mar 22 '19 at 04:48
  • @ChrisBrownie55 the result is same as above – user1687891 Mar 22 '19 at 04:48
  • Try parsing the `id` while sorting? (`parseInt`) – zerosand1s Mar 22 '19 at 04:50
  • Also, did you convert the object to an array before sorting? Because `.sort` doesn't exist on `Object` – Andria Mar 22 '19 at 04:50
  • 3
    You have *strings*, not *numbers*. Coerce them: `obj.sort((a,b) => (+a.id > +b.id) ? 1 : ((+b.id > +a.id) ? -1 : 0));`. Or simply `obj.sort((a, b) => +a.id - +b.id);`. – Gerardo Furtado Mar 22 '19 at 04:51
  • 1
    Wait, you are trying to sort an object? Objects aren't index based – wentjun Mar 22 '19 at 04:59
  • @wentjun That's not an object, you can see by the numbers on the left that OP probably copied an array from the console. – Gerardo Furtado Mar 22 '19 at 05:26
  • @GerardoFurtado Yeah, I was pretty confused. Sorry about that. He named his variable as `obj`, hence I kinda assumed its an object.. And that those are key-value pairs – wentjun Mar 22 '19 at 05:36

5 Answers5

3

So, something like this?

let op = [{id: "83", name: "(83) x"},
    {id: "84", name: "(84) y"},
    {id: "85", name: "(85) z"},
    {id: "86", name: "(86) a"},
    {id: "9", name: "(9) b"}].sort((a,b) => {
        const nA = Number(a.id);
        const nB = Number(b.id);

        return (nA > nB) ? 1 : ((nB > nA) ? -1 : 0)
    });
    
console.log(op)

When you compare "83" to "9", you're comparing strings. Just like "Alfred" comes before "Zac" just because of the first letter, "83" comes before "9" just because of the first letter.

Note: As you can see from different answers and comments, your sorting function is a bit wordy. You can simplify by returning something like this nA - nB instead of the whole (nA > nB) ? 1 : ((nB > nA) ? -1 : 0). Or you can even make it a single line function with coercion . There are a couple of answers here that use coercion, if you go that route you should accept one of their answers

Axel
  • 414
  • 1
  • 7
  • 21
  • 1
    I have updated your code. added code to code snippet. if you find anything not in sync of what you meant let me know or revert it back. – Code Maniac Mar 22 '19 at 05:08
  • A simple `return nA - nB` would serve its purpose: more elegant and easy to read – Davide Vitali Mar 22 '19 at 05:30
  • @DavideVitali you're right. But I usually try to use OP's own work to answer their question. I like to provide exactly what they are missing so it's easy for them to see what they had to do. However, given that it _is_ better to have an `a - b` thing, I'll edit my answer – Axel Mar 22 '19 at 05:34
3

You don't need to force -1, 1 and 0 results, because if result is negative, order will maintain and if it positive it will swap, so you can just subtract them:

let arr = [{id: "83", name: "(83) x"},
    {id: "84", name: "(84) y"},
    {id: "85", name: "(85) z"},
    {id: "86", name: "(86) a"},
    {id: "9", name: "(9) b"}];
    
    
let resp = arr.sort((a, b) => parseInt(a.id) - parseInt(b.id));

console.log(resp);
guijob
  • 4,413
  • 3
  • 20
  • 39
2

I have an alternative solution to the methods which are mentioned over here.

First, we convert the object to array. Next, we have to provide a custom sorting function. We sort it by making use of localeCompare, and passing the numeric: true option to localeCompare. I have left the locale as undefined, but you may pass in your own locale options, depending on your use case.

const obj = {
  64: {id: "83", name: "(83) x"},
  65: {id: "84", name: "(84) y"},
  66: {id: "85", name: "(85) z"},
  67: {id: "86", name: "(86) a"},
  68: {id: "9", name: "(9) b"}
}

const result = Object.values(obj).sort((a,b) => {
  return a['id'].localeCompare(b['id'], undefined, {numeric: true});
});

console.log(result);

If you would prefer to squeeze everything onto one line,

const result = Object.values(obj).sort((a,b) => a['id'].localeCompare(b['id'],undefined, {numeric: true}));

Please read up more about JavaScript's sort method, as I have noticed that you are trying to 'directly' sort an object/dictionary using JavaScript's sort. It has to be in array format.

wentjun
  • 40,384
  • 10
  • 95
  • 107
2

Your id is string so convert it to int in order to sort it . Use parseInt instead .

var obj=[{id: "83", name: "(83) x"},{id: "84", name: "(84) y"},{id: "85", name: "(85) z"},{id: "86", name: "(86) a"},{id: "9", name: "(9) b"}];
obj.sort((a, b) => {
            return parseInt(a.id )> parseInt(b.id);
        });
        
console.log(obj);
manikant gautam
  • 3,521
  • 1
  • 17
  • 27
2

Please see this short solution

obj.sort((a,b) => +a.id-+b.id)
Vikash_Singh
  • 1,856
  • 2
  • 14
  • 27