Reputation: 328
How can I achieve this without using any library? I have tried it with some ES6 function but it ended up duplicating some items in the array. It should return unique especially when there is no child array in the array
I have three array variables:
data1 = first data
data2 = variable to be merge with data1
data3 = result of the merged variables
let data1 = [{
"document_id": 12264,
"detail_info": [{
"id": 745,
"lot_no": "X12345",
},
{
"id": 744,
"lot_no": "Z12345",
}
]
},
{
"document_id": 12226,
"detail_info": [{
"id": 738,
"lot_no": "B12345",
},
{
"id": 739,
"lot_no": "C12345",
}
]
},
{
"document_id": 12221,
"detail_info": []
}
]
let data2 = [{
"document_id": 12264,
"detail_info": [{
"id": 744,
"lot_no": "Z12345",
},
{
"id": 743,
"lot_no": "L12345",
}
]
},
{
"document_id": 12226,
"detail_info": [{
"id": 739,
"lot_no": "C12345",
}]
},
{
"document_id": 12229,
"detail_info": [{
"id": 741,
"lot_no": "E12345",
}]
},
{
"document_id": 10095,
"detail_info": []
}
]
//**This should be the result**
let data3=[
{
"document_id": 12264,
"detail_info": [
{
"id": 745,
"lot_no": "X12345",
},
{
"id": 744,
"lot_no": "Z12345",
},
{
"id": 743,
"lot_no": "L12345",
}
]
},
{
"document_id": 12226,
"detail_info": [
{
"id": 738,
"lot_no": "B12345",
},
{
"id": 739,
"lot_no": "C12345",
}
]
},
{
"document_id": 12221,
"detail_info": []
},
{
"document_id": 12229,
"detail_info": [
{
"id": 741,
"lot_no": "E12345",
}
]
},
{
"document_id": 10095,
"detail_info": []
}
]
Upvotes: 3
Views: 319
Reputation: 13993
First concatenate data1
and data2
into a single array ([...data1, ...data2]
).
Then with Array.reduce()
, generate a dictionary whose keys are all possible document_id
found in the array.
Inside reduce
, when an entry already exists for a document_id
, then you have to merge the detail_info
together. Create an array of all detail_info
from the existing entry and the current item and remove the duplicates using a Set
that you generate from the detail_info.id
, then map this Set
of ids to the the corresponding detail_info
entries.
Finally, convert the dictionary to an array with Object.values()
:
const data1 = [
{ "document_id": 12264, someData: 'hello', "detail_info": [{ "id": 745, "lot_no": "X12345" }, { "id": 744, "lot_no": "Z12345" }] },
{ "document_id": 12226, "detail_info": [{ "id": 738, "lot_no": "B12345" }, { "id": 739, "lot_no": "C12345" }] },
{ "document_id": 12221, "detail_info": [] }
];
const data2 = [
{ "document_id": 12264, "detail_info": [{ "id": 744, "lot_no": "Z12345" }, { "id": 743, "lot_no": "L12345" }] },
{ "document_id": 12226, "detail_info": [{ "id": 739, "lot_no": "C12345" }] },
{ "document_id": 12229, "detail_info": [{ "id": 741, "lot_no": "E12345" }] },
{ "document_id": 10095, "detail_info": [] }
];
const distinctById = arr => [...new Set(arr.map(({ id }) => id))]
.map(id => arr.find(info => info.id === id))
const data3 = Object.values([...data1, ...data2].reduce((acc, x) => {
acc[x.document_id] = acc[x.document_id] || { ...x, detail_info: [] };
acc[x.document_id].detail_info = distinctById([...acc[x.document_id].detail_info, ...x.detail_info]);
return acc;
}, {}));
console.log(data3);
If you want to keep your detail_info
array ordered by insertion, do this:
const distinctById = arr => {
const uniqueIds = new Set(arr.map(({ id }) => id));
return arr.filter(({ id }) => uniqueIds.delete(id));
}
console.log(distinctById([{ id: 5 }, { id: 4 }, { id: 5 }, { id: 3 }, { id: 4 }]))
Upvotes: 2
Reputation: 44135
If you just want to combine two arrays, use concat
:
let data3 = data1.concat(data2);
Upvotes: 0