2

I have a JSON object like below:

[
    {
        "name": "Robert",
        "age":32,
        "country": "UK"
    },
    {
        "name": "Prasad",
        "age":28,
        "country": "India"
    },
    {
        "name": "Benny",
        "age":45,
        "country": "USA"
    },
    {
        "name": "Robin",
        "age":34,
        "country": "UK"
    },
    {
        "name": "Bob",
        "age":20,
        "country": "India"
    }
]

I have applied the array sorting for "name" column alone. I want to apply sort for “name” column first and then “age”.

This is how i sort the array by name:

var sort_by = function(field, reverse, primer){
   var key = primer ? 
     function(x) {return primer(x[field])} : 
     function(x) {return x[field]};
     reverse = [-1, 1][+!!reverse];
     return function (a, b) {
            return a = key(a), b = key(b), reverse * ((a > b) - (b > a));
        }
} 

Call the sort function:

arrayToSort.sort(
    sort_by( “name”, true, function(a){
    return a.toUpperCase();
}) );   

How can I get the array sorted like below?

[{
    "name": "Bob",
    "age":20,
    "country": "India"
},
{
    "name": "Benny",
    "age":45,
    "country": "USA"
},
{
    "name": "Prasad",
    "age":28,
    "country": "India"
},
{
    "name": "Robert",
    "age":32,
    "country": "UK"
},
{
    "name": "Robin",
    "age":34,
    "country": "UK"
}]

3 Answers 3

1

I think what you are looking for is a way to "chain" sort_by(..) calls so as to be able to operate on more than one field.

Below is a slightly modified version of your code. Its pretty much self-explanatory.

arrayToSort = [ ...];

var sort_by = function(field, reverse, primer){
    var key = primer ? 
         function(x) {return primer(x[field]); }:
         function(x) {return x[field] };
    reverse = [-1, 1][+!!reverse];
    return function (a, b) {
        a = key(a);
        b = key(b);
        return a==b ? 0 : reverse * ((a > b) - (b > a));
                    //^ Return a zero if the two fields are equal!
    }
}

var chainSortBy = function(sortByArr) {
    return function(a, b) {
        for (var i=0; i<sortByArr.length; i++) {
            var res = sortByArr[i](a,b);
            if (res != 0)
                return res; //If the individual sort_by returns a non-zero,
                            //we found inequality, return the value from the comparator.
        }
        return 0;
    }
}

arrayToSort.sort(
    chainSortBy([
        sort_by( "name", true, function(a){
            return a.toUpperCase();
        }),
        sort_by("age", true, null)
    ])
);

console.log(arrayToSort); //Check browser console.

For output: check the JSFiddle

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

Comments

0

The solution is back to native, just :

function orderByProp(arr,prop){

  var order = [], ordered=[];
    //create temp ID and Save the real index
  for(i=0; i < arr.length;++i){ order.push(arr[i][prop]+"-:-"+i);} 

  ordered.sort();

  for(i=0; i < arr.length;++i){
     var val = order.split("-:-");
     ordered.push(arr[val[1]]); Get the real array by saved index
  }
  return ordered;
}
// Apply
var arr = [{
    "name": "Bob",
    "age":20,
    "country": "India"
  },
  {
    "name": "Benny",
    "age":45,
    "country": "USA"
  },
  {
    "name": "Prasad",
    "age":28,
    "country": "India"
  },
  {
    "name": "Robert",
    "age":32,
    "country": "UK"
  },
  {
    "name": "Robin",
    "age":34,
    "country": "UK"
  }];
  var sort = orderByProp(arr,"name");

i'm not tested this. but hope it could solve your problems

Comments

0

This is relatively trivial with the Array.sort method by using the || operator, where it will use the second value if the first comparison returns 0, meaning the value was the same:

const data = [
  {
    "name": "Robert",
    "age": 32,
  },
  {
    "name": "David",
    "age": 24,
  },
  {
    "name": "Robert",
    "age": 28,
  },
];

const sortedData = data.sort((a, b) => a.name.localeCompare(b.name) || a.age - b.age);

console.log(sortedData);

Credit for this goes to @NinaScholz for her answer here.

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.