-1

I have a following array of objects:

[
  0: {
    id: 1,
    type: 'input'   
  },
  1: {
    id: 2,
    type: 'boolean'   
  },
  2: {
    id: 3,
    type: 'choice'   
  },
  3: {
    id: 1,
    type: 'select'   
  },
]

I want to sort the array element based on the value of type. If type is 'choice' I want to place the element in the last place of array i.e. 4th place. If type is 'boolean', place it in third place. If type is 'select', place it in second place.

I know how to sort an array with numerical values.

arr.sort((a, b) => {
  if (a.type < b.type) return -1
  return a.type > b.type ? 1 : 0
})

I am having problem comparing property values and sorting it.

Please help me. Any help will be highly appreciated.

Regards,

Sujan Shrestha
  • 1,020
  • 1
  • 18
  • 32

2 Answers2

1

Usually if need to sort an array based on some string property of object you need to create another which represents the order of sort. Then use indexOf and subtract the indexes

const order = ['input', 'select', 'boolean','choice'];

const arr = [
  {
    id: 1,
    type: 'input'   
  },
  {
    id: 2,
    type: 'boolean'   
  },
  {
    id: 3,
    type: 'choice'   
  },
  {
    id: 1,
    type: 'select'   
  },
]

arr.sort((a, b) => order.indexOf(a.type) - order.indexOf(b.type));
console.log(arr)
Maheer Ali
  • 35,834
  • 5
  • 42
  • 73
1

If you had

const arr = [
  {
    id: 1,
    type: 'input',
    val: 1
  },
  {
    id: 2,
    type: 'boolean',
    val: 3
  },
  {
    id: 3,
    type: 'choice',
    val: 4,
  },
  {
    id: 1,
    type: 'select',
    val: 2
  },
]

then it would be easy: just arr.sort((a, b) => a.val - b.val)

Since you don't have the property val, you can just set it on before:

const typeToValue = {
  input: 1,
  boolean: 3,
  choice: 4,
  select: 2
}
arr.forEach(el => {
  el.val = typeToValue[el.type]
})
arr.sort((a, b) => a.val - b.val)

Maybe you don't want to dirty your elements, notice that el.val == typeToValue[el.type]

Meaning you can write arr.sort((a, b)=>typeToValue[a.type] - typeToValue[b.type])

Finally should you have a sorted array ['input', 'select', 'boolean', 'choice'] you can trivially transform it to typeToValue object via Array.prototype.reduce

const orders = ['input', 'select', 'boolean', 'choice']
const typeToValue = orders.reduce((o, el, i) => (o[el] = i, o), {})

or if you don't like reduce with Object.fromEntries

const typeToValue = Object.fromEntries(orders.map((el, i) => [el, i]))

const arr = [{"id":1,"type":"input"},{"id":2,"type":"boolean"},{"id":3,"type":"choice"},{"id":1,"type":"select"}]
const orders = ['input', 'select', 'boolean', 'choice']
const typeToValue1 = orders.reduce((o, el, i) => (o[el] = i, o), {})
const typeToValue2 = Object.fromEntries(orders.map((el, i) => [el, i]))

// just slice to copy array because sort modify in place
console.log(arr.slice(0).sort((a, b)=>typeToValue1[a.type] - typeToValue1[b.type]))
console.log(arr.slice(0).sort((a, b)=>typeToValue2[a.type] - typeToValue2[b.type]))
grodzi
  • 5,633
  • 1
  • 15
  • 15