简体   繁体   中英

How to sort array by object property with multiple conditions in Javascript

I've been reading similar solved problems but couldn't understand how to apply it in my case.

So, I have an unsorted array of objects:

const queues = [
  {"floor":2,"direction":"REQUEST_FLOOR"},
  {"floor":1,"direction":"REQUEST_FLOOR"},
  {"floor":5,"direction":"CALL_DOWN"},
  {"floor":8,"direction":"CALL_DOWN"},
  {"floor":7,"direction":"REQUEST_FLOOR"},
  {"floor":6,"direction":"CALL_DOWN"}
];

I'd like to sort it into:


const queues = [
  {"floor":1,"direction":"REQUEST_FLOOR"},
  {"floor":2,"direction":"REQUEST_FLOOR"},
  {"floor":7,"direction":"REQUEST_FLOOR"},
  {"floor":8,"direction":"CALL_DOWN"},
  {"floor":6,"direction":"CALL_DOWN"},
  {"floor":5,"direction":"CALL_DOWN"},
];

So, the priority rules I want to apply are:

  1. Sort "REQUEST_FLOOR" first then only "CALL_DOWN".
  2. Sort "REQUEST_FLOOR" in ascending and "CALL_DOWN" in descending.

I'm able to make it work by separating it into 2 different arrays, sort, then combine it at the end. Here is my code:

const requestFloors = queues.filter(queue => queue.direction === "REQUEST_FLOOR");
const callDownFloors = queues.filter(queue => queue.direction === "CALL_DOWN");
requestFloors.sort((a,b) => a.floor - b.floor);
callDownFloors.sort((a,b) => b.floor - a.floor);
const newQueues = [...requestFloors,...callDownFloors];

Question: Instead of filtering + sorting, I'd like to just use sort(), so maybe something like this: queues.sort((a,b) => b.direction.localeCompare(a.direction) || a.floor - b.floor ); However, this code sort the the direction correctly, but the problem is it still sorts the floor in ascending for both direction.

How do I achieve the same result by only using sort()? Any helps will be greatly appreciated.

You can use the sort function:

queues.sort((el1, el2) => {
     if(el1.direction ==  el2.direction){
         if(el1.direction === "REQUEST_FLOOR")
            return el1.floor - el2.floor 
         else 
            return el2.floor - el1.floor
     } 
     else if(el1.direction === "REQUEST_FLOOR") 
         return -1;
     else 
         return 1;
})

Output:

[
   {
      "floor":1,
      "direction":"REQUEST_FLOOR"
   },
   {
      "floor":2,
      "direction":"REQUEST_FLOOR"
   },
   {
      "floor":7,
      "direction":"REQUEST_FLOOR"
   },
   {
      "floor":8,
      "direction":"CALL_DOWN"
   },
   {
      "floor":6,
      "direction":"CALL_DOWN"
   },
   {
      "floor":5,
      "direction":"CALL_DOWN"
   }
]

If the direction is the same in both compared items, you can conditionally choose the evaluation of the other columns based on the direction:

queues.sort((a,b) =>
  (a.direction=="CALL_DOWN") - (b.direction=="CALL_DOWN") ||
  (a.direction == "CALL_DOWN"
    ? b.floor - a.floor
    : a.floor - b.floor)
);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM