3

I have variable that defines the order of objects like this:

const order = ['large', 'medium', 'small'];

I want to match that order of data array objects using names from order array:

const data = [{name: "small", children: []}, {name: "medium", children: []}, {name: "large", children: []}]

so the effect should be following:

const data = [{name: "large", children: []}, {name: "medium", children: []}, {name: "small", children: []}]

How can I achieve this ?

Michał Lach
  • 1,291
  • 4
  • 18
  • 37
  • 1
    you could use a custom sort function that compares the index of matched word in the order array. – Webber Nov 24 '20 at 16:42

5 Answers5

4

We can do this by using the index of the name in the order array:

const order = ['large', 'medium', 'small'];
const data = [{name: "small", children: []}, {name: "medium", children: []}, {name: "large", children: []}];

const sortArray = (arr, order) => {
  return data.sort((a, b) => order.indexOf(a.name) - order.indexOf(b.name)); 
}
console.log(sortArray(data, order));
Fullstack Guy
  • 16,368
  • 3
  • 29
  • 44
2

using lodash

_(data).sortBy([(x) => {
    return order.findIndex(y => y.name === x.name);
}]).value();
Dmitriy
  • 391
  • 1
  • 8
1

I suggess : data = data.sort(item => order.indexOf(item.name))

or data = data.sort(item => -order.indexOf(item.name))

1

You could use a custom sort function that compares the index of matched word in the order array.

Something like

const order = ['large', 'medium', 'small'];
const data = [{name: "small", children: []}, {name: "medium", children: []}, {name: "large", children: []}]

const result = data.sort((a, b) => order.indexOf(a) < order.indexOf(b) ? 1 : -1);

console.log(result)
Webber
  • 4,672
  • 4
  • 29
  • 38
1

If your actual arrays are big, then try to avoid a scan in each call of the sort callback function, as that will mean the algorithm has a time complexity of O(n²logn). It can be done in linear time if you first convert the order information into a map (potentially in the form of a plain object) and use bucket sort:

const order = ['large', 'medium', 'small'];
const data = [{name: "small", children: []}, {name: "medium", children: []}, {name: "large", children: []}];


// preprocessing  O(n)    
const map = Object.fromEntries(order.map((key, i) => [key, i]));
let result = order.map(() => []);
// bucket sort  O(n)
for (let obj of data) result[map[obj.name]].push(obj);
// flatten O(n)
result = result.flat();
console.log(result);
trincot
  • 317,000
  • 35
  • 244
  • 286