I have problem with comparing 2 arrays of objects. I was searching lodash documentation, but I was not able to find proper method. The thing is that I need to compare objects by different keys.
private parentArray: {}[] = [
{ Id: 1, Name: 'A' },
{ Id: 2, Name: 'B' },
{ Id: 3, Name: 'C' },
{ Id: 4, Name: 'D' }
];
private childArray: {}[] = [
{ Id: 2, parentId: 2, Name: 'a' },
{ Id: 3, parentId: 2, Name: 'b' },
{ Id: 4, parentId: 4, Name: 'c' },
{ Id: 5, parentId: 4, Name: 'd' }
];
I need to make a new array of nested objects where 'parentId' will be matched with 'Id' of parent which will look like that:
private newArray = [
{ Id: 1, Name: 'A', Children: [] },
{
Id: 2,
Name: 'B',
Children: [
{ Id: 2, parentId: 2, Name: 'a' },
{ Id: 3, parentId: 2, Name: 'b' }
]
},
{
Id: 3,
Name: 'C',
Children: []
},
{
Id: 4,
Name: 'D',
Children: [
{ Id: 4, parentId: 4, Name: 'c' },
{ Id: 5, parentId: 4, Name: 'd' }
]
}
];
I was using '.intersectionWith([arrays], [comparator])' and '.isMatchWith(object, source, [customizer])' but it did not give me what I need. I will be grateful for any help.
The simplest way to do this is probably
const newArray = parentArray.map(
p => ({ ...p, Children: childArray.filter(c => c.parentId === p.Id) })
)
which results in the output you are looking for. Note that this is not necessarily the best performing algorithm in the case where parentArray
and childArray
are large, since we are looping over the entire childArray
for every element in parentArray
(so if childArray
is length 𝑐 and parentArray
is length 𝑝 then this algorithm is O(𝑝×𝑐)).
If such performance matters then you can do it by iterating over each element in childArray
and parentArray
once (which is O(𝑝+𝑐) assuming hash lookups are O(1)), like this:
type Parent = typeof parentArray[number];
type Child = typeof childArray[number];
interface New extends Parent {
Children: Child[];
}
const newArray: New[] = [];
const parentLookup: Record<number, New> = {};
for (const p of parentArray) {
const n = { ...p, Children: [] };
newArray.push(n)
parentLookup[p.Id] = n;
}
for (const c of childArray) {
parentLookup[c.parentId]?.Children.push(c);
}
console.log(newArray);