robtot
robtot

Reputation: 1031

Sort an array based on multiple conditions in Node.js

I am having difficulties sorting an array of objects properly. This is the expected result and explanation of the sorting conditions:

Test data:

POST   /pet​/{petId}​/uploadImage
POST   /pet
PUT    /pet
GET    /pet​/findByStatus
GET    /pet​/{petId}
POST   /pet​/{petId}
DELETE /pet​/{petId}
POST   /store​/order
GET    /store​/order​/{orderId}
DELETE /store​/order​/{orderId}
GET    /store​/inventory

Step 1 - Sort on depth (amount of backslashes in the string)

POST   /pet
PUT    /pet
GET    /pet​/{petId}
POST   /pet​/{petId}
DELETE /pet​/{petId}
GET    /pet​/findByStatus
POST   /store​/order
GET    /store​/inventory
GET    /store​/order​/{orderId}
DELETE /store​/order​/{orderId}
POST   /pet​/{petId}​/uploadImage

Step 2 - Sort alphabetically regardless of string length

POST   /pet
PUT    /pet
GET    /pet​/findByStatus
GET    /pet​/{petId}
POST   /pet​/{petId}
DELETE /pet​/{petId}
POST   /pet​/{petId}​/uploadImage
GET    /store​/inventory
POST   /store​/order
GET    /store​/order​/{orderId}
DELETE /store​/order​/{orderId}

Step 3 - Sort identical strings based on their request-method in order POST, PUT, GET, DELETE

POST   /pet
PUT    /pet
GET    /pet​/findByStatus
POST   /pet​/{petId}
GET    /pet​/{petId}
DELETE /pet​/{petId}
POST   /pet​/{petId}​/uploadImage
GET    /store​/inventory
POST   /store​/order
GET    /store​/order​/{orderId}
DELETE /store​/order​/{orderId}

Currently, I am just trying to perform steps 1 and 2. Step 1 works, but I guess I use the wrong logic to perform Step 2 as I do not sort the strings alphabetically regardless length, and Step 3 I am confused about because I need to base it on four conditions (POST, PUT, GET, DELETE) and not two as the sorting function expects. Here is the code:

function main() {
    let arr = [];
    arr.push({ "path": "/pet", "method": "POST" });
    arr.push({ "path": "/pet", "method": "PUT" });
    arr.push({ "path": "/store​/order", "method": "POST" });
    arr.push({ "path": "/store​/inventory", "method": "GET" });
    arr.push({ "path": "/store​/order​/{orderId}", "method": "GET" });
    arr.push({ "path": "/store​/order​/{orderId}", "method": "DELETE" });
    arr.push({ "path": "/pet​/{petId}​/uploadImage", "method": "POST " });
    arr.push({ "path": "/pet​/{petId}", "method": "GET" });
    arr.push({ "path": "/pet​/{petId}", "method": "POST" });
    arr.push({ "path": "/pet​/{petId}", "method": "DELETE" });
    arr.push({ "path": "/pet​/findByStatus", "method": "GET" });

  arr.sort(function(a, b) {
    const aCount = (a.path.match(/\//g) || []).length;
    const bCount = (b.path.match(/\//g) || []).length;

    if (aCount < bCount) {
      return -1;
    } else if (aCount > bCount) {
      return 1;
    } else {
      const aChars = a.path.split("").sort().join("");
      const bChars = b.path.split("").sort().join("");

      if (aChars < bChars) {
        return -1;
      } else if (aChars > bChars) {
        return 1
      } else {
        return 0;
      }
    }
  });

  for (const x of arr) {
    console.log(x.path);
  }
}

main();

Thankful for your help.

Upvotes: 1

Views: 424

Answers (1)

Owen Kelvin
Owen Kelvin

Reputation: 15083

You need to invert the order of your sorting in the code i.e start from step 3 then 2 then 1. That way the resulting array would be sorted from step 1 then 2 then 3. Below is a simple illustration

const arr = [{"path":"/pet","method":"POST"},{"path":"/pet","method":"PUT"},{"path":"/store/order","method":"POST"},{"path":"/store/inventory","method":"GET"},{"path":"/store/order/{orderId}","method":"GET"},{"path":"/store/order/{orderId}","method":"DELETE"},{"path":"/pet/{petId}/uploadImage","method":"POST "},{"path":"/pet/{petId}","method":"GET"},{"path":"/pet/{petId}","method":"POST"},{"path":"/pet/{petId}","method":"DELETE"},{"path":"/pet/findByStatus","method":"GET"}]

const multiSort = (arr) => 
  arr.sort(({method: a}, {method: b}) => {
    const sortOrder = ['POST', 'PUT', 'GET', 'DELETE'];
    return sortOrder.indexOf(a) > sortOrder.indexOf(b) ? 1 : -1
   })
     .sort(({path: a}, {path: b}) => a < b ? -1 : 1)
     .sort(({path: a}, {path: b}) =>
       (a.match(/\//g) || []).length < (b.match(/\//g) || []).length ? -1 : 1)

function main() {
  console.log(multiSort(arr))
} 

  main();

Upvotes: 1

Related Questions