sort array of objects by order of the property in a fixed format

110 Views Asked by At

I need to sort an array of object by property with the following order. For the first item in the list: it is either Camel or Absolute For the second item in the list: it has to be Dream, For the third item in the list: it has to be Carnival

[Camel, Dream, Carnival] or [Absolute,  Dream, Carnival]

Example 1: Given

 var items = [
     { 'Name':'Carnival', 'TypeId':3, ... },
     { 'Name':'Camel', 'TypeId':55, ... },
    { 'Name':'Dream', 'TypeId':4 , ...},
    ]

it should return:

var itemsSorted = [{ 'Name':'Camel', 'TypeId':55, ... },
    { 'Name':'Dream', 'TypeId':4, ... },
    { 'Name':'Carnival', 'TypeId':3, ... }]

Example 2: given

   var items = [
     { 'Name':'Carnival', 'TypeId':3, ... },
    { 'Name':'Dream', 'TypeId':4 , ...},
    { 'Name':'Absolute', 'TypeId':114 , ...}]

it should return:

   var itemsSorted = [{ 'Name':'Absolute', 'TypeId':114, ... },
    { 'Name':'Dream', 'TypeId':4, ... },
     { 'Name':'Carnival', 'TypeId':3, ... }]

My attempt which works, but I am wondering if there are any other solutions that is more elegant that you could recommend?

private _setUpdateProgress() {
   const order = ['Camel', 'Absolute', 'Dream', 'Carnival'];
   this.itemsSorted = [];

   if (this.items?.length) {
      for (let i = 0; i < order.length; i++) {
        if (i === 1) {
          continue;
        }
        let info!: Array<any>;
        if (i === 0) {
          info = items.filter(x => x.Name === 
              order[0] || x.Name === order[1]);
        }
        if (i > 1) {
          info = items.filter(x => x.Name=== 
              order[i]);
        }
        this.itemsSorted.push(info[0]);
     }
    }
2

There are 2 best solutions below

4
On BEST ANSWER

To create a more elegant solution for sorting the array of objects based on a specific order, you can utilize a custom sorting function that maps the names to their desired positions. This approach leverages the sort() function and a predefined order map, making it concise and readable.

Here's an example:

function sortItems(items) {
  const orderMap = {
    'Camel': 1,
    'Absolute': 1,
    'Dream': 2,
    'Carnival': 3
  };

  return items.sort((a, b) => {
    let orderA = orderMap[a.Name] || Number.MAX_VALUE;
    let orderB = orderMap[b.Name] || Number.MAX_VALUE;

    // Handle tie-breaker for 'Camel' and 'Absolute'
    if (orderA === orderB && orderA === 1) {
      return a.Name === 'Camel' ? -1 : 1;
    }

    return orderA - orderB;
  });
}

// Example usage
var items = [{
    'Name': 'Carnival',
    'TypeId': 3
  },
  {
    'Name': 'Camel',
    'TypeId': 55
  },
  {
    'Name': 'Dream',
    'TypeId': 4
  }
];

var itemsSorted = sortItems(items);
console.log(itemsSorted);

This solution uses a custom sorting function with a predefined orderMap to sort the array of objects. It handles the special case for 'Camel' and 'Absolute' with a tie-breaker. This approach is more concise and maintainable compared to manually iterating and filtering the array.

1
On

You could define an object that maps these strings to numbers, and then use the sort callback to compare these numbers:

const order = { "Camel": 1, "Absolute": 2, "Dream": 3, "Carnival": 4 };

const mySort = arr => arr.sort((a, b) => order[a.Name] - order[b.Name]); 

// Example runs
var items = [
    { 'Name':'Carnival', 'TypeId':3,  },
    { 'Name':'Camel', 'TypeId':55,  },
    { 'Name':'Dream', 'TypeId':4 , },
];
console.log(mySort(items));

items = [
    { 'Name':'Carnival', 'TypeId':3, },
    { 'Name':'Dream', 'TypeId':4 , },
    { 'Name':'Absolute', 'TypeId':114 , }
];
console.log(mySort(items));