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 ?

1
  • 1
    you could use a custom sort function that compares the index of matched word in the order array. Commented Nov 24, 2020 at 16:42

5 Answers 5

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));

Sign up to request clarification or add additional context in comments.

Comments

2

using lodash

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

Comments

1

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

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

Comments

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)

Comments

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);

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.