How do I combine 2 nested arrays. There are 2 Array A and B
const A = [
{
"id": 0,
"bp": true,
"ba": "value1",
"risk": [
{
"id": 0.1,
"rk": false,
"title": "risk1",
"control": [
{
"id": 0.12,
"ctl": "ctl1"
},
{
"id": 0.13,
"ctl": "ctl2"
}
]
},
{
"id": 0.1223,
"rk": false,
"title": "risk23"
}
],
"master": [
{
"id": 0.2,
"mk": false,
"title": "obli1",
"control": [
{
"id": 0.12,
"ctl": "ctl1"
}
]
}
]
},
{
"id": 2,
"bp": true,
"ba": "value2"
}
]
.
const B = [
{
"id": 0,
"bp": true,
"ba": "value1",
"risk": [
{
"id": 0.1,
"rk": false,
"title": "risk1",
"control": [
{
"id": 0.12,
"ctl": "ctl1"
},
{
"id": 0.13,
"ctl": "ctl2"
}
]
}
],
"master": [
{
"id": 0.2,
"mk": false,
"title": "obli1",
"control": [
{
"id": 0.12,
"ctl": "ctl1"
}
]
},
{
"id": 0.211,
"mk": true,
"title": "obli44",
"control": [
{
"id": 0.12,
"ctl": "ctl1"
}
]
}
]
},
{
"id": 3,
"bp": true,
"ba": "value3"
}
]
.
on combining A and B the output should be of below format. We need to take risk from table A and we need to take master from table B and add it to table C.
The Final array looks like the following.
.
const c = [
{
"id": 0,
"bp": true,
"ba": "value1",
"risk": [
{
"id": 0.1,
"rk": false,
"title": "risk1",
"control": [
{
"id": 0.12,
"ctl": "ctl1"
},
{
"id": 0.13,
"ctl": "ctl2"
}
]
},
{
"id": 0.1223,
"rk": false,
"title": "risk23"
}
],
"master": [
{
"id": 0.2,
"mk": false,
"title": "obli1",
"control": [
{
"id": 0.12,
"ctl": "ctl1"
}
]
},
{
"id": 0.211,
"mk": true,
"title": "obli44",
"control": [
{
"id": 0.12,
"ctl": "ctl1"
}
]
}
]
},
{
"id": 2,
"bp": true,
"ba": "value2"
},
{
"id": 3,
"bp": true,
"ba": "value3"
}
]
The data can be more than 1000 records. please help me with which it will save time and complexity.
Thanks in Advance.
CodePudding user response:
The first thing you need to do is to isolate the IDs from array A and B. You can also map over the two of them concatenated together, but then you may have duplicate values. This seems like a rational way to go about ensuring single entries for each ID.
const allIds = [...a.map(x => x.id), ...b.map(x => x.id)];
const uniqueIds = allIds.reduce((prev, curr) => {
return prev.includes(curr) ? prev : [...prev, curr]
}, []);
Then you need to take those uniqueIds
, and map over each of them. For each ID, you need to return the matching object in A and the matching object in B, but overwrite the risk
property with the value from the object in A and overwrite the master
property with the value from the object in B.
That can be done by just finding the matching objects in A and B, and then use the spread operator to assign their entries to the new object.
Note: If the properties outside of risk
and master
(e.g. bp
or ba
) have different values, then the element listed last will overwrite it. In the below case, that means if the bp
value in A is true
and the bp
value in B is false
, then the bp
value in C will be false
.
const c = uniqueIds.map(id => {
const elementInA = a.find(x => x.id === id);
const elementInB = b.find(x => x.id === id);
return {
...elementInA,
...elementInB,
risk: [
...elementInA?.risk ?? []
],
master: [
...elementInB?.master ?? []
]
};
});
CodePudding user response:
Instead of looping through multiple times both arrays, I would suggest something that will loop through each array, not more than needed.
The following approach will loop through twice the first array, and once the B array. (not considering the indexOf method).
const ids = A.map(({id}) => id), C = A.map(a => a);
for(let b of B){
let index = ids.indexOf(b.id);
if(index < 0){
C.push(b);
} else {
C[index] = {
...A[index],
...b,
risk: [
...A[index]?.risk ?? []
],
master: [
...b?.master ?? []
]
}
}
}