-1

I have this JavaScript array of Objects:

data = [
    {'deviation': 57.41, 'provider': "This", 'measure': "median"},
    {'deviation': 49.02, 'provider': "All", 'measure': "median"},
    {'deviation': 199.67, 'provider': "This", 'measure': "third_quartile"},
    {'deviation': 152.31, 'provider': "All", 'measure': "third_quartile"},
    {'deviation': 41.48, 'provider': "This", 'measure': "first_quartile"},
    {'deviation': -1.07, 'provider': "All", 'measure': "first_quartile"}
]

and I would like to sort it both by 'provider' (the three "This" before the three "All") and by 'measure' (first quartile, median, third quartile), so the resulting array will look like:

data = [
    {'deviation': 41.48, 'provider': "This", 'measure': "first_quartile"},
    {'deviation': 57.41, 'provider': "This", 'measure': "median"},
    {'deviation': 199.67, 'provider': "This", 'measure': "third_quartile"},
    {'deviation': -1.07, 'provider': "All", 'measure': "first_quartile"}
    {'deviation': 49.02, 'provider': "All", 'measure': "median"},
    {'deviation': 152.31, 'provider': "All", 'measure': "third_quartile"},       
]

I have written a function as an argument to .sort(), and it does return the array sorted by 'provider', but then when I feed it into the same function with measure as an argument (thankfully, first_quartile, median, third_quartile are already alphabetically sorted the way I want them) - the sorting gets broken. How can I go about doing it?

EDIT The functions I have been using:

var compare_prv = function(a,b) {
  if (a.provider < b.provider){
    return 1;
  }
  return 0;
}

var compare_meas = function(a,b) {
  if (a.measure < b.measure){
    return -1;
  }
  return 0;
}
nvergos
  • 432
  • 3
  • 15

2 Answers2

2

It sounds like you are doing:

data.sort(function(a, b) {
    //sort by provider
});

data.sort(function(a, b) {
    //sort by measure
});

But what you want to do is:

data.sort(function(a, b) {
    //sort by provider, but if they are equal, sort by measure
});

So something like

data.sort(function(a, b) {
    if (a.provider === b.provider) {
        return a.measure.localeCompare(b.measure);
    }
    return b.provider.localeCompare(a.provider);
});
dave
  • 62,300
  • 5
  • 72
  • 93
0

You could chain the sorting criteria with logical OR ||.

For a set of strings with a defined order, you could use an object for getting the wanted order.

{
    first_quartile: 1,
    median: 2,
    third_quartile: 3
}

This lets you sort some item, if not in the order list ssort to start with default zero or to bottom with a huge value like Infinity.

In this case the pattern looks like

(order[a.measure] || 0) - (order[a.measure] || 0)                // to top
(order[a.measure] || Infinify ) - (order[a.measure] || Infinity) // to bottom

var array = [{ deviation: 57.41, provider: "This", measure: "median" }, { deviation: 49.02, provider: "All", measure: "median" }, { deviation: 199.67, provider: "This", measure: "third_quartile" }, { deviation: 152.31, provider: "All", measure: "third_quartile" }, { deviation: 41.48, provider: "This", measure: "first_quartile" }, { deviation: -1.07, provider: "All", measure: "first_quartile" }],
   order = { first_quartile: 1, median: 2, third_quartile: 3 };

array.sort(function (a, b) {
    return b.provider.localeCompare(a.provider) || order[a.measure] - order[b.measure];
});

console.log(array);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392