Skip to content Skip to sidebar Skip to footer

How To Sort An Array Of Objects With Labels According To Other Array Of Labels?

I want to sort an array of objects with labels, for example var arrayToBeSorted = [{label: 'firstLabel', value: 123}, {label: 'secondLabel', value: 456}, {label: 'thirdLabel', valu

Solution 1:

There are a couple of approaches:

  1. Using indexOf to repeatedly search the labels array

  2. Using a map so looking up the index of a label is quicker

Here's an example using indexOf (in ES2015+):

arrayToBeSorted.sort((a, b) => labels.indexOf(a.label) - labels.indexOf(b.label));

Live Copy:

var arrayToBeSorted = [{label: 'firstLabel', value: 123}, {label: 'secondLabel', value: 456}, {label: 'thirdLabel', value: 789}];

var labels = ['secondLabel', 'thirdLabel', 'fourthLabel', 'firstLabel'];

arrayToBeSorted.sort((a, b) => labels.indexOf(a.label) - labels.indexOf(b.label));

console.log(arrayToBeSorted);

Note that indexOf will return -1 if the label doesn't exist in labels, which will make unknown labels appear at the beginning of the result. If you want them at the end instead, check for -1 and replace it with Infinity.

Here's an example using a map to speed up finding those indexes (in ES2015+):

const map = newMap(labels.map((label, index) => [label, index]));
arrayToBeSorted.sort((a, b) => {
    let aindex = map.get(a.label);
    if (aindex === null) {
        aindex = -1; // Or Infinity if you want them at the end
    }
    let bindex = map.get(b.label);
    if (bindex === null) {
        bindex = -1; // ""
    }
    return aindex - bindex;
});

Live Copy:

var arrayToBeSorted = [{label: 'firstLabel', value: 123}, {label: 'secondLabel', value: 456}, {label: 'thirdLabel', value: 789}];

var labels = ['secondLabel', 'thirdLabel', 'fourthLabel', 'firstLabel'];

const map = newMap(labels.map((label, index) => [label, index]));
arrayToBeSorted.sort((a, b) => {
    let aindex = map.get(a.label);
    if (aindex === null) {
        aindex = -1; // Or Infinity if you want them at the end
    }
    let bindex = map.get(b.label);
    if (bindex === null) {
        bindex = -1; // ""
    }
    return aindex - bindex;
});

console.log(arrayToBeSorted);

That's written for clarity and to avoid looking up the labels more than once in the callback. It can be more concise at the cost of a second label lookup in the map:

constmap = new Map(labels.map((label, index) => [label, index]));
arrayToBeSorted.sort((a, b) => {
    const aindex = map.has(a.label) ? map.get(a.label) : -1; // Or Infinity if you want them at the endconst bindex = map.has(b.label) ? map.get(b.label) : -1; // "return aindex - bindex;
});

Live Copy:

var arrayToBeSorted = [{label: 'firstLabel', value: 123}, {label: 'secondLabel', value: 456}, {label: 'thirdLabel', value: 789}];

var labels = ['secondLabel', 'thirdLabel', 'fourthLabel', 'firstLabel'];

const map = newMap(labels.map((label, index) => [label, index]));
arrayToBeSorted.sort((a, b) => {
    const aindex = map.has(a.label) ? map.get(a.label) : -1; // Or Infinity if you want them at the endconst bindex = map.has(b.label) ? map.get(b.label) : -1; // "return aindex - bindex;
});

console.log(arrayToBeSorted);

It can even be:

constmap = new Map(labels.map((label, index) => [label, index]));
arrayToBeSorted.sort((a, b) =>
    (map.has(a.label) ? map.get(a.label) : -1) - (map.has(b.label) ? map.get(b.label) : -1)
);

...but for me that's making life too difficult when debugging, etc.

Solution 2:

You need to provide priority to values as per second array. here we are building a Map from second array name as key and index as priority. so you can use Map and default value and sort

var arrayToBeSorted = [{label: 'firstLabel', value: 123}, {label: 'secondLabel', value: 456}, {label: 'thirdLabel', value: 789}]
var labels = ['secondLabel', 'thirdLabel', 'fourthLabel', 'firstLabel']

let mapper = newMap(labels.map((v, i) => [v, i + 1]))

let final = arrayToBeSorted.sort((a, b) => {
  return (mapper.get(a.label) || Infinity) - (mapper.get(b.label) || Infinity)
})

console.log(final)

Solution 3:

You can create a custom order and order by it:

var arrayToBeSorted = [
    {label: 'firstLabel', value: 123}, 
    {label: 'secondLabel', value: 456}, 
    {label: 'thirdLabel', value: 789}
];

let order = { secondLabel: 1, thirdLabel: 2, fourthLabel: 3, firstLabel: 4 };

arrayToBeSorted.sort((a, b) => {
  return order[a.label] - order[b.label];
});

console.log(arrayToBeSorted);

Solution 4:

Straight-forward using sort-array.

const sortArray = require('sort-array')

const arrayToBeSorted = [
  {label: 'firstLabel', value: 123},
  {label: 'secondLabel', value: 456},
  {label: 'thirdLabel', value: 789}
]

sortArray(arrayToBeSorted, {
  by: 'label',
  order: 'labelOrder',
  customOrders: {
    labelOrder: ['secondLabel', 'thirdLabel', 'fourthLabel', 'firstLabel']
  }
})

console.log(arrayToBeSorted)

Prints this output:

[
  { label:'secondLabel', value:456 },
  { label:'thirdLabel', value:789 },
  { label:'firstLabel', value:123 }
]

Post a Comment for "How To Sort An Array Of Objects With Labels According To Other Array Of Labels?"