I have 2 arrays, I'd like to combine them if they have the same two object keys.
If no match is found, still keep the object, but have the value as 0.
Example of Input
withdrawal: [
{
"id": "a1",
"withdrawalAmount": 300,
"user": "John"
},
{
"id": "b2",
"withdrawalAmount": 100,
"user": "Mike"
}
{
"id": "c3",
"withdrawalAmount": 33,
"user": "John"
}
]
deposit: [
{
"id": "a1",
"depositAmount": 123,
"user": "John"
},
{
"id": "c3",
"depositAmount": 44,
"user": "John"
},
]
Expected Output
transactions: [
{
"id": "a1",
"depositAmount": 123,
"withdrawalAmount": 300,
"user": "John"
},
{
"id": "b2",
"depositAmount": 0,
"withdrawalAmount": 100,
"user": "Mike"
},
{
"id": "c3",
"depositAmount": 44,
"withdrawalAmount": 33
"user": "John"
},
]
This is the function I tried so far, but it doesn't work due the two input arrays being a different length.
function mergeArrayObjects(arr1, arr2) {
return arr1.map((item, i) => {
if (item.user === arr2[i].user) {
//merging two objects
return Object.assign({}, item, arr2[i])
}
})
}
You can achieve the result you want by processing the list of withdrawals and deposits using Array.reduce to an object with the id values as keys and deposit and withdrawal amounts as values; you can then take the values of that object to make the transactions array:
const withdrawal = [{
"id": "a1",
"withdrawalAmount": 300,
"user": "John"
},
{
"id": "b2",
"withdrawalAmount": 100,
"user": "Mike"
}
]
const deposit = [{
"id": "a1",
"depositAmount": 123,
"user": "John"
},
{
"id": "c3",
"depositAmount": 44,
"user": "John"
}
]
const transactions = Object.values(
withdrawal
.concat(deposit)
.reduce((c, { id, depositAmount, withdrawalAmount, ...rest }) => {
c[id] = c[id] || {}
depositAmount = c[id]['depositAmount'] || depositAmount || 0;
withdrawalAmount = c[id]['withdrawalAmount'] || withdrawalAmount || 0;
c[id] = ({ id, depositAmount, withdrawalAmount, ...rest });
return c;
},
{})
)
console.log(transactions)
.as-console-wrapper { max-height: 100% !important; top: 0 }
If you want to group by both id and user, you need to make the result object keys out of both values, joined by a character that is not in either of them (e.g. # would work for your data):
const withdrawal = [{
"id": "a1",
"withdrawalAmount": 300,
"user": "John"
},
{
"id": "b2",
"withdrawalAmount": 100,
"user": "Mike"
}
]
const deposit = [{
"id": "a2",
"depositAmount": 123,
"user": "John"
},
{
"id": "b2",
"depositAmount": 109,
"user": "Mike"
},
{
"id": "c3",
"depositAmount": 44,
"user": "John"
}
]
const transactions = Object.values(
withdrawal
.concat(deposit)
.reduce((c, { id, user, depositAmount, withdrawalAmount, ...rest }) => {
key = `${id}#${user}`
c[key] = c[key] || {}
depositAmount = c[key]['depositAmount'] || depositAmount || 0;
withdrawalAmount = c[key]['withdrawalAmount'] || withdrawalAmount || 0;
c[key] = ({ id, user, depositAmount, withdrawalAmount, ...rest });
return c;
},
{})
)
console.log(transactions)
.as-console-wrapper { max-height: 100% !important; top: 0 }
Presented below is one possible way to achieve the desired objective.
Code Snippet
// helper method to obtain all props
// from array-elt matching "id"
const getInfo = (ar, argId) => (
ar?.find(({ id }) => id === argId) ?? {}
);
// combine both arrays using "id"
const combineArrays = (ar1, ar2) => {
// first get unique ids combining both arrays
const uniqIds = [
...new Set(
[...ar1, ...ar2]
.map(({ id }) => id)
)
];
// now, for each unique id
// simply get relevant info from both
// arrays where element's match the "id"
return uniqIds.map(id => ({
id,
...getInfo(ar1, id),
...getInfo(ar2, id)
}));
};
const withdrawal = [{
"id": "a1",
"withdrawalAmount": 300,
"user": "John"
},
{
"id": "b2",
"withdrawalAmount": 100,
"user": "Mike"
}
];
const deposit = [{
"id": "a1",
"depositAmount": 123,
"user": "John"
}];
// invoke the method and display the result
console.log(
'combined both arrays as below:\n',
combineArrays(withdrawal, deposit)
);
.as-console-wrapper { max-height: 100% !important; top: 0 }
Explanation
Inline comments added to the snippet above.
const withdrawal = [{
"id": "a1",
"withdrawalAmount": 300,
"user": "John"
},
{
"id": "b2",
"withdrawalAmount": 100,
"user": "Mike"
}
]
const deposit = [{
"id": "a1",
"depositAmount": 123,
"user": "John"
}, ]
const mergeArr = withdrawal.map(ele => {
let other = deposit.find(({id}) => id === ele.id)
return other ? {...ele, ...other} : {...ele, depositAmount : 0}
})
console.log(mergeArr)