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"
}]
UltraInstinct
  • 43,308
  • 12
  • 81
  • 104
Prasad G K
  • 136
  • 1
  • 7

3 Answers3

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

UltraInstinct
  • 43,308
  • 12
  • 81
  • 104
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

Mike
  • 1,231
  • 12
  • 17
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.

fredrivett
  • 5,419
  • 3
  • 35
  • 48