4

I would like to get your help about this little problem.

I have like to order this array depending on the code value but not in alphabetical order. (I specified this in bold but got eventually flagged anyway, people don't even care about reading the question)

For example I would like to have all the green objects, then all the blue ones and then all the red ones. What is the best way to do that?

[
    { code: "RED", value: 0},
    { code: "BLUE", value: 0},
    { code: "RED", value: 0},
    { code: "GREEN", value: 0},
    { code: "BLUE", value: 0},
    { code: "RED", value: 0},
    { code: "GREEN", value: 0},
    { code: "BLUE", value: 0}
]

Is it possible to do that with the sort function? What would the condition be in that case?

5
  • @JasperSeinhorst I just looped through the array, I wanted to see if there was a faster way. Commented Nov 7, 2017 at 13:09
  • @lilezek please read the question before flagging, I DON'T WANT IT TO BE ALPHABETICALLY ORDERED Commented Nov 7, 2017 at 13:09
  • 1
    @LucaDeNardi You just have to write your own sorting function, literally.
    – lilezek
    Commented Nov 7, 2017 at 13:11
  • @lilezek not true at all, since someone provided a faster way to do that. Commented Nov 7, 2017 at 13:13
  • 1
    @LucaDeNardi everyone here provided a sorting function.
    – lilezek
    Commented Nov 7, 2017 at 13:14

7 Answers 7

19

You could take an object for the wanted order.

var array = [{ code: "RED", value: 0 }, { code: "BLUE", value: 0 }, { code: "RED", value: 0 }, { code: "GREEN", value: 0 }, { code: "BLUE", value: 0 }, { code: "RED", value: 0 }, { code: "GREEN", value: 0 }, { code: "BLUE", value: 0 }],
    order = { GREEN: 1, BLUE: 2, RED: 3 };
    
array.sort(function (a, b) {
    return order[a.code] - order[b.code];
});

console.log(array);
.as-console-wrapper { max-height: 100% !important; top: 0; }

For unknow colors/values, you could use a default value with

  • 0, for sorting to top or
  • Infinity or as some suggest because of the ability for caculating Number.MAX_VALUE for sorting to the end,
  • or any other value for sorting inbetween the other groups.

At last you could sort the special treated items with an other sorting part, chained with logical OR ||.

var array = [{ code: "YELLOW", value: 0 }, { code: "BLACK", value: 0 }, { code: "RED", value: 0 }, { code: "BLUE", value: 0 }, { code: "RED", value: 0 }, { code: "GREEN", value: 0 }, { code: "BLUE", value: 0 }, { code: "RED", value: 0 }, { code: "GREEN", value: 0 }, { code: "BLUE", value: 0 }],
    order = { GREEN: 1, BLUE: 2, RED: 3, default: Infinity };
    
array.sort(function (a, b) {
    return (order[a.code] || order.default) - (order[b.code] || order.default) || a.code.localeCompare(b.code);
});

console.log(array);
.as-console-wrapper { max-height: 100% !important; top: 0; }

1
  • 1
    Mmm this is interesting! I didn't think about using an object to keep track of the order :) Commented Nov 7, 2017 at 13:10
3

Set the custom priority first

var codePriority = [ "GREEN", "BLUE", "RED" ];

Now use the same in sorting as

arr.sort( function(a,b){ 
   if ( a.code == b.code ) return a.value - b.value;
   return codePriority.indexOf( a.code ) - codePriority.indexOf( b.code ) ; notice this line
})

Demo

var arr = [
    { code: "RED", value: 0},
    { code: "BLUE", value: 0},
    { code: "RED", value: 0},
    { code: "GREEN", value: 0},
    { code: "BLUE", value: 0},
    { code: "RED", value: 0},
    { code: "GREEN", value: 0},
    { code: "BLUE", value: 0}
];
var codePriority = [ "GREEN", "BLUE", "RED" ];
arr.sort( function(a,b){ 
   if ( a.code == b.code ) return a.value - b.value;
   return codePriority.indexOf( a.code ) - codePriority.indexOf( b.code )
});
console.log( arr );

2
  • You can remove the if check. Try return codePriority.indexOf( a.code ) - codePriority.indexOf( b.code ) || a.value - b.value
    – Rajesh
    Commented Nov 7, 2017 at 13:16
  • @Rajesh ohh, didn't thought of that :)... I would keep this as is for now, its more readable. Commented Nov 7, 2017 at 13:19
1

You could implement a schema array and sort according to element's index inside that schema array.

const a = ['GREEN', 'BLUE', 'RED'];

const o = [{code:"RED",value:0},{code:"BLUE",value:0},{code:"RED",value:0},{code:"GREEN",value:0},{code:"BLUE",value:0},{code:"RED",value:0},{code:"GREEN",value:0},{code:"BLUE",value:0}];

const r = o.slice().sort(({ code: q }, { code: w }) => a.indexOf(q) - a.indexOf(w));

console.log(r);

0
1

this is a function for sorting by a specific color.

const colors = [{
    name: "T-shirt",
    color: "red",
    price: 20
  },
  {
    name: "Shoes",
    color: "yellow",
    price: 20
  },
  {
    name: "Pants",
    color: "red",
    price: 20
  },
  {
    name: "Cap",
    color: "yellow",
    price: 20
  },
  {
    name: "Skirt",
    color: "red",
    price: 15
  },
]

let sortByColor = color => colors.sort((a, b) => a.color === color ? -1 : 1)

console.log(sortByColor('red'))

1

You can use the sort function i.e Array.prototype.sort() Visit https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort

Firstly you have to decide whether you want to sort in ascending order or in descending order. To sort in ascending order you can do something like this:

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

An to do it in descending order:

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

Now suppose you want a certain color sorted and displayed first. You can have a function like this:

const sortByKeyAsc = (arr,color) =>
  arr.sort((a, b) => {
    if(a.color < b.color || (a.color === color && b.color !== color)){
      return -1;
    }
    if(a.color > b.color || (a.color !== color && b.color === color)){
      return 1
    }
    return 0;
  });

and you can use it like this:

const array1 = sortByKeyAsc(arr,'pink');
0

I was dealing with a case where I had to match a string status and sort by the various statuses specifically. .findIndex and .includes ended up being the best approach.

statusPriority sets the intended order. Once the indexes are found they can be compared and returned to the .sort

let records = [
  {status: 'Record is ready to submit.', active: true, name: 'A'},
  {status: 'Record has been sent.', active: true, name: 'B'},
  {status: 'Activation is required.', active: true, name: 'C'},
  {status: 'Record submission failed.', active: true, name: 'D'},
  {status: 'Creation is pending.', active: true, name: 'E'},
]

console.log(records.map(r => r.status))

let statusPriority = ['creation', 'activation', 'sent', 'ready', 'failed'];
records.sort((a, b) => {
  let aIndex = statusPriority.findIndex(status => a.status.toLowerCase().includes(status));
  let bIndex = statusPriority.findIndex(status => b.status.toLowerCase().includes(status));
  return aIndex - bIndex;
})

console.log(records.map(r => r.status))

0

You can sort color alphabetically by using this function

  var sortedArr = arr.sort((first, second)=>{
            
        return first.color < second.color ? -1 : 1
    })

Not the answer you're looking for? Browse other questions tagged or ask your own question.