如何根据两个对象键合并两个不同长度的对象数组
How to merge two object arrays of differing length, based on two object key
我有 2 个数组,如果它们具有相同的两个对象键,我想合并它们。
如果找不到匹配项,仍然保留该对象,但值为0。
输入示例
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"
},
]
预期输出
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"
},
]
这是我到目前为止尝试过的函数,但由于两个输入数组的长度不同,所以它不起作用。
function mergeArrayObjects(arr1, arr2) {
return arr1.map((item, i) => {
if (item.user === arr2[i].user) {
//merging two objects
return Object.assign({}, item, arr2[i])
}
})
}
您可以通过使用 Array.reduce
将 id
值作为键和 deposit
和 [=17= 的对象处理取款和存款列表来实现您想要的结果] 金额作为价值;然后您可以使用该对象的值来创建 transactions
数组:
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 }
如果您想同时按 id
和 user
进行分组,您需要从两个值中创建结果对象键,并由一个不在其中任何一个中的字符连接(例如#
适用于您的数据):
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 }
下面介绍的是实现所需 objective.
的一种可能方法
代码段
// 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 }
说明
在上面的代码段中添加了内联评论。
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)
在第一次迭代中仅合并公共对象,然后 re-iterate 两个数组并在最终数组中仅取 un-used 项。
class Transaction {
constructor(transaction) {
this.id = transaction.id;
this.depositAmount = transaction.depositAmount | 0;
this.withdrawAmount = transaction.withdrawalAmount | 0;
this.user = transaction.user;
}
}
let withdrawl = [
{
id: "a1",
withdrawalAmount: 300,
user: "John",
},
{
id: "b2",
withdrawalAmount: 100,
user: "Mike",
},
{
id: "c3",
withdrawalAmount: 33,
user: "John",
},
];
let deposit = [
{
id: "a1",
depositAmount: 123,
user: "John",
},
{
id: "c3",
depositAmount: 44,
user: "John",
},
];
let transactions = [];
// merge the common key of two array into one array
withdrawl.forEach((item1) => {
deposit.forEach((item2) => {
if (item1.id === item2.id) {
let combined = { ...item1, ...item2 };
let transaction = new Transaction(combined);
transactions.push(transaction);
// mark the item as used
// or set some flag to know
// the item is used in the array
item1.used = true;
item2.used = true;
}
})
})
// now take all the unused item from the both array
// and push them to the transactions array
withdrawl.forEach((item1) => {
if (!item1.used) {
let transaction = new Transaction(item1);
transactions.push(transaction);
}
});
deposit.forEach((item2) => {
if (!item2.used) {
let transaction = new Transaction(item2);
transactions.push(transaction);
}
});
console.log(transactions);
对于大型阵列,请使用 Nick 的 (最后你会节省很多周期)
对于数组中的少量项,find()
的解决方案就足够了:
const withdrawal= [
{
"id": "a1",
"withdrawalAmount": 300,
"user": "John"
},
{
"id": "b2",
"withdrawalAmount": 100,
"user": "Mike"
},
{
"id": "c3",
"withdrawalAmount": 33,
"user": "John"
}
]
const deposit= [
{
"id": "a1",
"depositAmount": 123,
"user": "John"
},
{
"id": "c3",
"depositAmount": 44,
"user": "John"
}
]
const transactions = withdrawal.map(item => ({"depositAmount": 0, ...item}));
deposit.forEach( item => {
const found = transactions.find(x => x.id === item.id);
if (found) {
Object.assign(found,item);
} else {
transactions.push(Object.assign(item,{"withdrawalAmount": 0}));
}
});
console.log(transactions)
注意:此代码假定您想要两个数组的并集而不是交集
我有 2 个数组,如果它们具有相同的两个对象键,我想合并它们。
如果找不到匹配项,仍然保留该对象,但值为0。
输入示例
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"
},
]
预期输出
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"
},
]
这是我到目前为止尝试过的函数,但由于两个输入数组的长度不同,所以它不起作用。
function mergeArrayObjects(arr1, arr2) {
return arr1.map((item, i) => {
if (item.user === arr2[i].user) {
//merging two objects
return Object.assign({}, item, arr2[i])
}
})
}
您可以通过使用 Array.reduce
将 id
值作为键和 deposit
和 [=17= 的对象处理取款和存款列表来实现您想要的结果] 金额作为价值;然后您可以使用该对象的值来创建 transactions
数组:
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 }
如果您想同时按 id
和 user
进行分组,您需要从两个值中创建结果对象键,并由一个不在其中任何一个中的字符连接(例如#
适用于您的数据):
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 }
下面介绍的是实现所需 objective.
的一种可能方法代码段
// 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 }
说明
在上面的代码段中添加了内联评论。
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)
在第一次迭代中仅合并公共对象,然后 re-iterate 两个数组并在最终数组中仅取 un-used 项。
class Transaction {
constructor(transaction) {
this.id = transaction.id;
this.depositAmount = transaction.depositAmount | 0;
this.withdrawAmount = transaction.withdrawalAmount | 0;
this.user = transaction.user;
}
}
let withdrawl = [
{
id: "a1",
withdrawalAmount: 300,
user: "John",
},
{
id: "b2",
withdrawalAmount: 100,
user: "Mike",
},
{
id: "c3",
withdrawalAmount: 33,
user: "John",
},
];
let deposit = [
{
id: "a1",
depositAmount: 123,
user: "John",
},
{
id: "c3",
depositAmount: 44,
user: "John",
},
];
let transactions = [];
// merge the common key of two array into one array
withdrawl.forEach((item1) => {
deposit.forEach((item2) => {
if (item1.id === item2.id) {
let combined = { ...item1, ...item2 };
let transaction = new Transaction(combined);
transactions.push(transaction);
// mark the item as used
// or set some flag to know
// the item is used in the array
item1.used = true;
item2.used = true;
}
})
})
// now take all the unused item from the both array
// and push them to the transactions array
withdrawl.forEach((item1) => {
if (!item1.used) {
let transaction = new Transaction(item1);
transactions.push(transaction);
}
});
deposit.forEach((item2) => {
if (!item2.used) {
let transaction = new Transaction(item2);
transactions.push(transaction);
}
});
console.log(transactions);
对于大型阵列,请使用 Nick 的
对于数组中的少量项,find()
的解决方案就足够了:
const withdrawal= [
{
"id": "a1",
"withdrawalAmount": 300,
"user": "John"
},
{
"id": "b2",
"withdrawalAmount": 100,
"user": "Mike"
},
{
"id": "c3",
"withdrawalAmount": 33,
"user": "John"
}
]
const deposit= [
{
"id": "a1",
"depositAmount": 123,
"user": "John"
},
{
"id": "c3",
"depositAmount": 44,
"user": "John"
}
]
const transactions = withdrawal.map(item => ({"depositAmount": 0, ...item}));
deposit.forEach( item => {
const found = transactions.find(x => x.id === item.id);
if (found) {
Object.assign(found,item);
} else {
transactions.push(Object.assign(item,{"withdrawalAmount": 0}));
}
});
console.log(transactions)
注意:此代码假定您想要两个数组的并集而不是交集