Shri
Shri

Reputation: 751

Javascript sort array of objects using array of priority

I have this array of objects:

var eventList = [
    {
        eventName: "abc",
        status: "completed"
    },
    {
        eventName: "def",
        status: "live"
    },
    {
        eventName: "ghi",
        status: "live"
    },
    {
        eventName: "jkl",
        status: "upcoming"
    },
]

I want to sort these array of objects using a priority array of a specific key, say ["live", "upcoming", "completed"] for status, meaning all live events come first, followed by upcoming followed by completed. Answers all over the internet seem like you can only sort array objects using keys as ascending or descending. How to I approach this?

Upvotes: 5

Views: 2773

Answers (2)

phi-rakib
phi-rakib

Reputation: 3302

You could do it using Array.prototype.sort() method with an ordering array.

const eventList = [
  {
    eventName: 'abc',
    status: 'completed',
  },
  {
    eventName: 'def',
    status: 'live',
  },
  {
    eventName: 'ghi',
    status: 'live',
  },
  {
    eventName: 'jkl',
    status: 'upcoming',
  },
];

const order = ['live', 'upcoming', 'completed'];
eventList.sort((x, y) => order.indexOf(x.status) - order.indexOf(y.status));
console.log(eventList);

If you would want to make index searching faster when sorting you could use Map Object.

const eventList = [
  {
    eventName: 'abc',
    status: 'completed',
  },
  {
    eventName: 'def',
    status: 'live',
  },
  {
    eventName: 'ghi',
    status: 'live',
  },
  {
    eventName: 'jkl',
    status: 'upcoming',
  },
];

const order = ['live', 'upcoming', 'completed'];
const map = new Map();
order.forEach((x, i) => map.set(x, i));
eventList.sort((x, y) => map.get(x.status) - map.get(y.status));
console.log(eventList);

Upvotes: 10

Nick Parsons
Nick Parsons

Reputation: 50759

You can do this without sorting for a linear time complexity by first grouping your array based on status, and then using .flatMap() on your order array. For each value in the ordered array, you can grab the grouped value from the grouping in O(1) (ie: instantly), and map those grouped objects. As you're using flatMap these grouped objects will be flattened into the resulting array:

const eventList = [ { eventName: "abc", status: "completed" }, { eventName: "def", status: "live" }, { eventName: "ghi", status: "live" }, { eventName: "jkl", status: "upcoming" }, ];

const order = ["live", "upcoming", "completed"];
const grouped = eventList.reduce(
  (map, o) => map.set(o.status, (map.get(o.status) || []).concat(o)), new Map
);

const result = order.flatMap(status => grouped.get(status) || []);
console.log(result);

Upvotes: 1

Related Questions