Javascript 通过匹配ID更新嵌套对象
我有一个包含嵌套对象的数组,如果它们匹配,我需要从另一个对象数组更新该数组 以下是我要更新的数据结构:Javascript 通过匹配ID更新嵌套对象,javascript,arrays,object,data-structures,Javascript,Arrays,Object,Data Structures,我有一个包含嵌套对象的数组,如果它们匹配,我需要从另一个对象数组更新该数组 以下是我要更新的数据结构: const invoices = { BatchItemRequest: [ { bId: "bid10", Invoice: { Line: [ { SalesItemLineDetail: { ItemAccountRef: { AccountCode: "10110" }, }, },
const invoices = {
BatchItemRequest: [
{
bId: "bid10",
Invoice: {
Line: [
{
SalesItemLineDetail: {
ItemAccountRef: { AccountCode: "10110" },
},
},
{
SalesItemLineDetail: {
ItemAccountRef: { AccountCode: "11110" },
},
Amount: 2499,
},
],
},
},
{
bId: "bid10",
Invoice: {
Line: [
{
SalesItemLineDetail: {
ItemAccountRef: { AccountCode: "10110" },
},
},
{
SalesItemLineDetail: {
ItemAccountRef: { AccountCode: "10111" },
},
Amount: 2499,
},
],
},
},
],
};
以下是我要从中更新的对象数组:
const accounts = [
{ AccountCode: "10110", Id: "84" },
{ AccountCode: "11110", Id: "5" },
{ AccountCode: "10111", Id: "81" },
];
我想使用accounts更新发票,如果AccountCode匹配,则插入Id,以获得以下结构:
const invoices = {
BatchItemRequest: [
{
bId: "bid10",
Invoice: {
Line: [
{
SalesItemLineDetail: {
ItemAccountRef: { AccountCode: "10110", Id: "84" },
},
},
{
SalesItemLineDetail: {
ItemAccountRef: { AccountCode: "11110", Id: "5" },
},
Amount: 2499,
},
],
},
},
{
bId: "bid10",
Invoice: {
Line: [
{
SalesItemLineDetail: {
ItemAccountRef: { AccountCode: "10110", Id: "84" },
},
},
{
SalesItemLineDetail: {
ItemAccountRef: { AccountCode: "10111", Id: "81" },
},
Amount: 2499,
},
],
},
},
],
};
我尝试过各种方法,例如:
const mapped = invoices.BatchItemRequest.map((item1) => {
return Object.assign(
item1,
accounts.find((item2) => {
return item2 && item1.Invoice.Line.ItemAccountRef.AccountCode === item2.AccountCode;
})
);
});
这种方法存在问题(我认为它不起作用,因为我需要做另一个嵌套映射),但它也创建了一个新数组,只包括发票的嵌套元素
有人知道一个很好的方法吗?这不是最干净的代码,但它完成了任务:
function matchInvoiceWithAccount(invoices, accounts) {
const mappedInvoices = invoices.BatchItemRequest.map((request) => {
// Shouldn't modify input parameter, could use Object.assign to create a copy and modify the copy instead for purity
request.Invoice.Line = request.Invoice.Line.map((line) => {
const accountCode = line.SalesItemLineDetail.ItemAccountRef.AccountCode;
// If accounts was a map of AccountCode to Id you would't need to search for it which would be more effective
const account = accounts.find((account) => account.AccountCode === accountCode);
if (account) {
line.SalesItemLineDetail.ItemAccountRef.Id = account.Id;
}
return line;
});
return request;
});
return {
BatchItemRequest: mappedInvoices,
};
}
要改进这一点,您可以而且可能应该做的是不修改函数的输入参数,但这需要您以更好的方式复制原始参数,可以使用Object.assign或spread运算符。这不是最干净的代码,但它完成了工作:
function matchInvoiceWithAccount(invoices, accounts) {
const mappedInvoices = invoices.BatchItemRequest.map((request) => {
// Shouldn't modify input parameter, could use Object.assign to create a copy and modify the copy instead for purity
request.Invoice.Line = request.Invoice.Line.map((line) => {
const accountCode = line.SalesItemLineDetail.ItemAccountRef.AccountCode;
// If accounts was a map of AccountCode to Id you would't need to search for it which would be more effective
const account = accounts.find((account) => account.AccountCode === accountCode);
if (account) {
line.SalesItemLineDetail.ItemAccountRef.Id = account.Id;
}
return line;
});
return request;
});
return {
BatchItemRequest: mappedInvoices,
};
}
要改善这一点,您可以而且可能应该做的是不修改函数的输入参数,但这需要您以更好的方式复制原始数据,可以使用Object.assign或spread运算符。首先,最好从帐户数组创建映射。我们将使用O(n)对数组执行一次操作,然后使用O(1)通过代码读取ID。嵌套的fors是O(m*n),这在大型数组中会慢得多
const idsByAccountCodes = new Map();
accounts.forEach((data) => {
idsByAccountCodes.set(data.AccountCode, data.Id);
})
或更短:
const idsByAccountCode = new Map(accounts.map((data) => [data.AccountCode, data.Id]))
然后,如果您想改变原始值,可以遍历所有嵌套级别并添加值
for ( const {Invoice:{ Line: line }} of invoices.BatchItemRequest){
for ( const {SalesItemLineDetail: {ItemAccountRef: item}} of line){
item.Id = idsByAccountCodes.get(item.AccountCode) || 'some default value'
// also if you don't have ids for all codes you need to define logic for that case
}
}
如果您不需要修改原始的大对象“发票”和所有嵌套对象,那么您可以使用lodash.cloneDeep之类的东西创建If的递归克隆。首先,最好从accounts数组创建映射。我们将使用O(n)对数组执行一次操作,然后使用O(1)通过代码读取ID。嵌套的fors是O(m*n),这在大型数组中会慢得多
const idsByAccountCodes = new Map();
accounts.forEach((data) => {
idsByAccountCodes.set(data.AccountCode, data.Id);
})
或更短:
const idsByAccountCode = new Map(accounts.map((data) => [data.AccountCode, data.Id]))
然后,如果您想改变原始值,可以遍历所有嵌套级别并添加值
for ( const {Invoice:{ Line: line }} of invoices.BatchItemRequest){
for ( const {SalesItemLineDetail: {ItemAccountRef: item}} of line){
item.Id = idsByAccountCodes.get(item.AccountCode) || 'some default value'
// also if you don't have ids for all codes you need to define logic for that case
}
}
如果您不需要修改原始的大对象“发票”和所有嵌套对象,那么您可以使用lodash之类的东西创建If的递归克隆。cloneDeep您的
帐户
数组必须是这样吗?作为帐户代码到Id
值的映射,使用它会容易得多您的帐户
数组必须是这样的吗?作为帐户代码到Id
values的映射,使用它会容易得多谢谢!非常好,谢谢!非常好,谢谢!很好,谢谢!效果很好