Reputation: 57
I have two arrays containing objects like so:
const array1 =
[
{
"id": 1,
"mass": 149,
"height": 180,
"dob": "2003-09-04"
},
{
"id": 2,
"mass": 140,
"height": 175,
"dob": "2000-02-12",
},
{
"id": 3,
"mass": 143,
"height": 170,
"dob": "2001-11-04"
}
]
const array2 =
[
{
"id": 1,
"name": "James",
"sport": "Football"
},
{
"id": 2,
"name": "Adam",
"sport": "Tennis"
}
]
I would like to merge them such that a combined array only contains data where the id
appears in both array1 and array2.
So far I'm using lodash _.merge
which returns:
const merged = _.merge(array1, array2)
merged = [
{
"id": 1,
"mass": 149,
"height": 180,
"dob": "2003-09-04",
"name": "James",
"sport": "Football"
},
{
"id": 2,
"mass": 140,
"height": 175,
"dob": "2000-02-12",
"name": "Adam",
"sport": "Tennis"
},
{
"id": 3,
"mass": 143,
"height": 170,
"dob": "2001-11-04" ,
}
]
I would just like merged
to contain data where id
appears in both, i.e:
[{
"id": 1,
"mass": 149,
"height": 180,
"dob": "2003-09-04",
"name": "James",
"sport": "Football"
},
{
"id": 2,
"mass": 140,
"height": 175,
"dob": "2000-02-12",
"name": "Adam",
"sport": "Tennis"
}]
I believe the equivalent function in something like SQL would be an "Inner join"
Any help would be greatly appreciated!
Upvotes: 2
Views: 479
Reputation: 171
this will merge the data where the id is the same id
const merged = array2.reduce((arr, current) => {
let array1Data = {...array1}[current.id];
if (array1Data) {
arr.push({...array1Data, ...current});
}
return arr;
}, []);
console.log(merged);
Upvotes: 0
Reputation: 25392
You can filter your first array with Array.filter
to only include objects that are present in your second array before performing the same merge.
let merged = array1.filter(e => array2.some(f => f.id == e.id));
const array1 =
[
{
"id": 1,
"mass": 149,
"height": 180,
"dob": 2003-09-04
},
{
"id": 2,
"mass": 140,
"height": 175,
"dob": 2000-02-12,
},
{
"id": 3,
"mass": 143,
"height": 170,
"dob": 2001-11-04
}
]
const array2 =
[
{
"id": 1,
"name": "James",
"sport": "Football"
},
{
"id": 2,
"name": "Adam",
"sport": "Tennis"
}
]
let merged = array1.filter(e => array2.some(f => f.id == e.id));
merged = _.merge(merged, array2);
console.log(merged);
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js"></script>
Upvotes: 1
Reputation: 207511
You need to map them from one to the other. Basic idea using reduce where we track the item by the id.
const array1 = [{
"id": 1,
"mass": 149,
"height": 180,
"dob": '2003-09-04'
},
{
"id": 2,
"mass": 140,
"height": 175,
"dob": '2000-02-12',
},
{
"id": 3,
"mass": 143,
"height": 170,
"dob": '2001-11-04'
}
]
const array2 = [{
"id": 1,
"name": "James",
"sport": "Football"
},
{
"id": 2,
"name": "Adam",
"sport": "Tennis"
}
]
const result = Object.values([...array1, ...array2].reduce((acc, userData) => {
// have you seen the id before? If yes, use it, if no use and empty object
const data = acc[userData.id] || {};
//merge the objects together and store the updated data by the id
acc[userData.id] = { ...data, ...userData };
return acc
}, {}));
console.log(result);
Now that will include everything. If you only want the items that are in both, you can do it in two loops.
const array1 = [{
"id": 1,
"mass": 149,
"height": 180,
"dob": '2003-09-04'
},
{
"id": 2,
"mass": 140,
"height": 175,
"dob": '2000-02-12',
},
{
"id": 3,
"mass": 143,
"height": 170,
"dob": '2001-11-04'
}
]
const array2 = [{
"id": 1,
"name": "James",
"sport": "Football"
},
{
"id": 2,
"name": "Adam",
"sport": "Tennis"
}
]
// create a look up by the id
const array1MappedById = array1.reduce((acc, userData) => {
acc[userData.id] = userData;
return acc
}, {});
// Loop over the second array and make a new array with the merged data
const result = array2.reduce((arr, userData) => {
const array1Data = array1MappedById[userData.id];
// if the data exists in the map, then we should merge the data
if (array1Data) {
arr.push({...array1Data, ...userData});
}
return arr;
}, []);
console.log(result);
Upvotes: 2