user2924127
user2924127

Reputation: 6240

Custom sorting of response in javascript

I have the following response I get from my server:

[
{"key":{"name":"1","kind":"a"},
{"key":{"name":"1","kind":"ap"},
{"key":{"name":"5","kind":"ap"}
]

The responses come in a different order every time as the server does not guarantee order. Thus I need to sort the response like this after I receive it:

First sort so the smallest KIND is first so 'a' should come before 'b'. I then need to make it so name of the username is the first ordered within the 'a'.

var username = '5';

var response = [
{"key":{"name":"1","kind":"a"},
{"key":{"name":"1","kind":"ap"},
{"key":{"name":"5","kind":"ap"}
];

response = entities.sort(function (a, b) {
                        if (a.key.kind != b.key.kind){ return a.key.kind < b.key.kind}
                        else if(a.key.name == username){ return a.key.name < b.key.name }
                        else return a.key.name > b.key.name;
                    });

This is the code I use to sort, but it does not work. It sorts the KIND correctly, but then when it needs to sort by NAME (username should come before other names) it does not work.

The actual result I get is equal to this:

[
{"key":{"name":"1","kind":"ap"},
{"key":{"name":"5","kind":"ap"},
{"key":{"name":"1","kind":"a"}
]

But the result I want is this:

[
{"key":{"name":"5","kind":"ap"},
{"key":{"name":"1","kind":"ap"},
{"key":{"name":"1","kind":"a"}
]

As you can see my username is equal to 5, so {"key":{"name":"5","kind":"ap"} should come before {"key":{"name":"1","kind":"ap"} .

Upvotes: 1

Views: 519

Answers (3)

Paul Boutes
Paul Boutes

Reputation: 3315

When you use .sort() methods, you have to pass a compare function which will say who should comes first between two elements.

When you are comparing numbers, you can simply do :

function compare(a, b) {
  return a - b;
}

this will sort an array of numbers ascending.

However, when you are comparing string, you have to define some ordering criterion, in order to tell which element should be comes first.

  • If compare(a, b) is less than 0, sort a to a lower index than b, so a comes first.
  • If compare(a, b) is greater than 0, sort b to a lower index than a, so b comes first.
  • If compare(a, b) is equal to 0, there is no change

So will get something like :

function compare(a, b) {
  if (a is lower than b by your criteria) {
    return -1;
  }
  if (a is greater than b by your criteria) {
    return 1;
  }
  return 0;
}

In your case, you can write function generator that takes the property of the object to sort, and a custom sort function. This is useful when the function needs to be applied in more than one situation.

const username = '5';

const response = [
{"key":{"name":"1","kind":"a"}},
{"key":{"name":"1","kind":"ap"}},
{"key":{"name":"5","kind":"ap"}}
];

//Retrieve the value at 'props' into 'obj'
function retrieve(props, obj) {
  return props.reduce((result, current) => {
      result = result[current];
      return result;
    }, obj);
}



//Custom sort function for Kind properties
function sortKind(a, b) {
   return a < b ? -1 : (a > b) ? 1 : 0;
}



//Custom sort function for name properties
function sortName(a, b) {
  return a === username ? -1 : 1;
}



//Generic sort function
function sortByProp(...props) {
  const callback = props.pop();
  return function(a, b) {
    const v1 = retrieve(props, a);
    const v2 = retrieve(props, b);
    return callback(v1, v2);
  } 
}


//Then you just have to call your sort function, and you can chain them
const res = response
          .sort(sortByProp('key', 'kind', sortKind))
          .sort(sortByProp('key', 'name', sortName));

console.log(res);

You can see here a Working plunker

Upvotes: 1

vp_arth
vp_arth

Reputation: 14992

return a.key.name < b.key.name is not saying that a < b.
They actually will be compared.
Try to replace it with return -1; to say to comparator:

a is lesser than b in that case. 

Upvotes: 3

amaksr
amaksr

Reputation: 7745

You missed "return" in this line

else if(a.key.name == username){ a.key.name < b.key.name }

Upvotes: 0

Related Questions