I've been stuck on this problem for a few days now.
let data1 = [{
project_code: "110",
project_text: "SampleProject1",
location: "Seattle",
startingCost: 0,
actualCost: 399.99
},
{
project: "110",
project_text: "SampleProject1",
location: "Bellevue",
startingCost: 0,
actualCost: 599.99
}];
let data2 = [{
project: "110",
project_text: "SampleProject1",
location: "Seattle",
startingCost: 249.99,
actualCost: ""
},
{
project: "110",
project_text: "SampleProject1",
location: "Bellevue",
startingCost: 699.99,
actualCost: ""
},
{
project: "110",
project_text: "SampleProject1",
location: "North Gate",
startingCost: 899.99,
actualCost: 1199.99
}]
The end goal here is that i want it to be merged into one array and the values should be updated like this:
let output = [{
project: "110",
project_text: "SampleProject1",
location: "Seattle",
startingCost: 249.99, // FROM DATA2
actualCost: 399.99 // FROM DATA1
},
{
project: "110",
project_text: "SampleProject1",
location: "Bellevue",
startingCost: 699.99, // FROM DATA2
actualCost: 599.99 // FROM DATA1
},
{
// THIS ONE IS ADDING IN NEW DATA
project: "110",
project_text: "SampleProject1",
location: "North Gate",
startingCost: 899.99,
actualCost: 1199.99
},
]
I would much prefer a vanilla JS approach but i'll be ok with Lodash as long as i get the output closer to that.
let data1 = [{project_code: "110",project_text: "SampleProject1",location: "Seattle",startingCost: 0,actualCost: 399.99},{project: "110",project_text: "SampleProject1",location: "Bellevue",startingCost: 0,actualCost: 599.99}];
let data2 = [{project: "110",project_text: "SampleProject1",location: "Seattle",startingCost: 249.99,actualCost: ""},{project: "110",project_text: "SampleProject1",location: "Bellevue",startingCost: 699.99,actualCost: ""},{project: "110",project_text: "SampleProject1",location: "North Gate",startingCost: 899.99,actualCost: 1199.99}]
data2.forEach((obj) => {
let ob = data1.find((e) => e.location == obj.location);
// YOU CAN ADD OTHER CONDTIONS HERE WITH && OPERATOR
if (ob !== undefined) {
obj.actualCost = ob.actualCost;
}
});
console.log(data2);
The above code will override data2.
let data1 = [{project_code: "110",project_text: "SampleProject1",location: "Seattle",startingCost: 0,actualCost: 399.99},{project: "110",project_text: "SampleProject1",location: "Bellevue",startingCost: 0,actualCost: 599.99}];
let data2 = [{project: "110",project_text: "SampleProject1",location: "Seattle",startingCost: 249.99,actualCost: ""},{project: "110",project_text: "SampleProject1",location: "Bellevue",startingCost: 699.99,actualCost: ""},{project: "110",project_text: "SampleProject1",location: "North Gate",startingCost: 899.99,actualCost: 1199.99}]
var final_result = [];
data2.forEach(({...obj}) => {
let ob = {...data1.find((e) => e.location == obj.location)};
//{...data}; used to Clone Object without reference to do not override data1
if (Object.keys(ob).length !== 0) {
ob.startingCost = obj.startingCost;
final_result.push(ob);
} else {
final_result.push(obj);
}
});
console.log(final_result);
forEach(({...obj})
) used to restrict modifying data2 object when modifying final_resultThis is how I would do it. Like the comments suggested, which property is suppose to be unique? It would be the criteria I would use to find the data in the other array, I used location because that is the only thing that seemed to be different. You can of course use more than one property to find a match like:
item.project === obj.project && item.location === obj.location
data2.forEach(obj=>{
let object1 = data1.find(item=>item.location === obj.location);
if(object1){
object1.startingCost = object1.startingCost || obj.startingCost;
object1.actualCost = object1.actualCost || obj.actualCost;
}
else{
data1.push(obj);
}
})
This would default to keeping the data from data1 array if both arrays have data for an object. So change it around for what your program needs are.
Try using Array.reduce
.
Logic
data2
with Array.reduce
.data1
from data2
.startingCost
and actualCost
.data1
has already been covered in result. If that is not covered, push the missing node to result.
const data1 = [{
project: "110",
project_text: "SampleProject1",
location: "Seattle",
startingCost: 0,
actualCost: 399.99
},
{
project: "110",
project_text: "SampleProject1",
location: "Bellevue",
startingCost: 0,
actualCost: 599.99
}];
const data2 = [{
project: "110",
project_text: "SampleProject1",
location: "Seattle",
startingCost: 249.99,
actualCost: ""
},
{
project: "110",
project_text: "SampleProject1",
location: "Bellevue",
startingCost: 699.99,
actualCost: ""
},
{
project: "110",
project_text: "SampleProject1",
location: "North Gate",
startingCost: 899.99,
actualCost: 1199.99
}];
const result = data2.reduce((acc, curr) => {
const matchingNode = data1.find((node) =>
node.project === curr.project &&
node.project_text === curr.project_text &&
node.location === curr.location);
if(matchingNode) {
const updatedNode = { ...matchingNode }; // Take a copy of matching node
updatedNode.startingCost = matchingNode.startingCost || curr.startingCost;
updatedNode.actualCost = matchingNode.actualCost || curr.actualCost;
acc.push(updatedNode);
} else {
acc.push(curr);
}
return acc;
}, []);
// Since we have looped through data2 to generate the array,
// we have to ensure that we have not missed any node from data1 aswell
data1.forEach((node) => {
const matchingNode = result.find((resultNode) =>
node.project === resultNode.project &&
node.project_text === resultNode.project_text &&
node.location === resultNode.location);
if (!matchingNode) {
result.push(node);
}
})
console.log(result);