I am a bit stuck on this one: I have a array of objects ordered according to a hierarchy (parent_id
), something as follow:
let myArray = [
{ id: 1, parent_id: null, score: 20, type: 1 },
{ id: 12, parent_id: 1, score: 25, type: 2 },
{ id: 23, parent_id: 12, score: 55, type: 3 },
{ id: 35, parent_id: 12, score: 25, type: 3 },
{ id: 10, parent_id: null, score: 75, type: 1 },
{ id: 25, parent_id: 10, score: 15, type: 2 },
{ id: 100, parent_id: 25, score: 88, type: 3 }
]
Now I would like to maintain the hierarchy order, but also order the elements by score to obtain something like this:
let expected = [
{ id: 10, parent_id: null, score: 75, type: 1 },
{ id: 25, parent_id: 10, score: 15, type: 2 },
{ id: 100, parent_id: 25, score: 88, type: 3 },
{ id: 1, parent_id: null, score: 20, type: 1 },
{ id: 12, parent_id: 1, score: 25, type: 2 },
{ id: 23, parent_id: 12, score: 55, type: 3 },
{ id: 35, parent_id: 12, score: 25, type: 3 },
]
I am writing pretty inefficient code with nested foreach
that almost work, but nor quite yet. I was wondering if there was a neater solution. (pretty sure there is, but too smart for me).
Also in my code I am relaying on the type
attribute, but ideally I would not use it for sorting.
Note: this data is just an example, the real array is bigger and the number of children for each parent vary.
Since my explanation is not great we can think of hierarchy in this way
type:1
-> Country
type:2
-> State
type:3
-> City
So I need to order by score desc
like this
- Country
- State
- City
- City
- State
- City
- Country and so on...
Thank you to anyone who is willing to land me an hand,
A single sort does not work, because of the parent children relation which is not respected while sorting the data.
This approach works in three parts:
score
, because the following tree is build in insertation order.var data = [{ id: 1, parent_id: null, score: 20, type: 1 }, { id: 12, parent_id: 1, score: 25, type: 2 }, { id: 23, parent_id: 12, score: 55, type: 3 }, { id: 35, parent_id: 12, score: 25, type: 3 }, { id: 10, parent_id: null, score: 75, type: 1 }, { id: 25, parent_id: 10, score: 15, type: 2 }, { id: 100, parent_id: 25, score: 88, type: 3 }]
.sort(function (a, b) { return b.score - a.score; }),
tree = function (data, root) {
var r = [], o = {};
data.forEach(function (a) {
o[a.id] = { data: a, children: o[a.id] && o[a.id].children };
if (a.parent_id === root) {
r.push(o[a.id]);
} else {
o[a.parent_id] = o[a.parent_id] || {};
o[a.parent_id].children = o[a.parent_id].children || [];
o[a.parent_id].children.push(o[a.id]);
}
});
return r;
}(data, null), // null is the root value of parent_id
sorted = tree.reduce(function traverse(r, a) {
return r.concat(a.data, (a.children || []).reduce(traverse, []));
}, [])
console.log(sorted);
console.log(tree);
.as-console-wrapper { max-height: 100% !important; top: 0; }