slotdp02
slotdp02

Reputation: 438

Sorting array of objects by properties (multi-level)

I have an array of objects that is like this:

var array = [
    {minutes: 45, hours: 4, meridiem: "PM"},
    {minutes: 00, hours: 8, meridiem: "AM"},
    {minutes: 45, hours: 8, meridiem: "AM"},
    {minutes: 30, hours: 3, meridiem: "PM"},
    {minutes: 15, hours: 11, meridiem: "AM"},
    {minutes: 00, hours: 1, meridiem: "PM"}
]

Essentially I need to sort by time, earliest first. So by AM/PM then by hours and then by minutes if hours and meridiem are equal.

Here is what I've tried

this.currentTours.sort(function(a,b) {
  if (a.meridiem != b.meridiem) {
    return 1
  }
  if ((a.dateR.meridiem == b.dateR.meridiem) && a.dateR.hours != 
  b.dateR.hours) {
    return 1
  }
  if (((a.dateR.meridiem == b.dateR.meridiem) && a.dateR.hours != 
  b.dateR.hours) && a.dateR.minutes != b.dateR.minutes) {
    return 1
  }
  return a.dateR.meridiem - b.dateR.meridiem
})

Getting past 1 layer of properties is where I get stuck.

Upvotes: 2

Views: 89

Answers (2)

Nina Scholz
Nina Scholz

Reputation: 386600

You could use a chained approach for a nested sorting, with a hour correction for 12 am or pm. These values are interpreted as zero.

(a.hours < 12) * a.hours

var array = [{ minutes: 45, hours: 4, meridiem: "PM" }, { minutes: 00, hours: 8, meridiem: "AM" }, { minutes: 45, hours: 8, meridiem: "AM" }, { minutes: 30, hours: 3, meridiem: "PM" }, { minutes: 15, hours: 11, meridiem: "AM" }, { minutes: 00, hours: 1, meridiem: "PM" }, { minutes: 00, hours: 12, meridiem: "PM" },{ minutes: 00, hours: 12, meridiem: "AM" }];

array.sort(function (a, b) {
    return (b.meridiem === 'AM') - (a.meridiem === 'AM')
        || (a.hours < 12) * a.hours - (b.hours < 12) * b.hours
        || a.minutes - b.minutes;
});

console.log(array);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Upvotes: 3

Gershom Maes
Gershom Maes

Reputation: 8150

You can use simple if statements in the Array.prototype.sort method to take multiple properties into account.

If two properties are exactly equal, consult the next most substantial property to break such ties.

var array = [
  { minutes: 45, hours: 4, meridiem: "PM" },
  { minutes: 00, hours: 8, meridiem: "AM" },
  { minutes: 45, hours: 8, meridiem: "AM" },
  { minutes: 30, hours: 3, meridiem: "PM" },
  { minutes: 15, hours: 11, meridiem: "AM" },
  { minutes: 00, hours: 1, meridiem: "PM" }
];

array.sort(function(a, b) {
  if (a.meridiem !== b.meridiem)
    return a.meridiem === 'AM' ? -1 : 1;
  
  if (a.hours !== b.hours)
    return a.hours - b.hours;
  
  return a.minutes - b.minutes
});

console.log(array);

Upvotes: 1

Related Questions