javascript - 在嵌套对象数组中,如何访问先前的对象值并增加一个 fileld
问题描述
我有两个对象数组
- 钱包
wallets = [
{ title: "Wallet 1", _id: "1", created: new Date("2020-07-14T00:00:00.000Z") },
{ title: "Wallet 2", _id: "2", created: new Date("2020-07-13T00:00:00.000Z") },
{ title: "Wallet 3", _id: "3", created: new Date("2020-07-19T00:00:00.000Z") }]
- 交易
tcode = [
{ "createdOn": "2020-03-16T11:58:52.000Z", "type": "Credit", "_id": 2, "amount": 212.92, walletId: 1 },
{ "createdOn": "2020-01-01T15:21:58.000Z", "type": "Credit", "_id": 3, "amount": 624.22, walletId: 2 },
{ "createdOn": "2019-12-13T20:50:38.000Z", "type": "Credit", "_id": 4, "amount": -874.15, walletId: 3 },
{ "createdOn": "2020-05-25T22:37:20.000Z", "type": "Credit", "_id": 5, "amount": -502.68, walletId: 1 },
{ "createdOn": "2020-01-24T10:33:27.000Z", "type": "Debit", "_id": 6, "amount": 897.46, walletId: 2 },
{ "createdOn": "2019-09-24T00:45:15.000Z", "type": "Debit", "_id": 7, "amount": 981.36, walletId: 1 },
{ "createdOn": "2019-12-06T22:17:35.000Z", "type": "Credit", "_id": 8, "amount": -934.81, walletId: 2 },
{ "createdOn": "2019-09-06T03:49:31.000Z", "type": "Credit", "_id": 9, "amount": 818.77, walletId: 3 },
{ "createdOn": "2020-04-23T22:09:46.000Z", "type": "Credit", "_id": 10, "amount": 312.33, walletId: 3 },
{ "createdOn": "2020-07-18T09:15:12.000Z", "type": "Credit", "_id": 11, "amount": -739.77, walletId: 1 }
]
现在我正在遍历钱包过滤对象并使用升序对它们进行排序
for (let i in wallets){
temp = tcode.filter(data => data.walletId == wallets[i]._id).sort(((a, b) => { return new Date(b.createdOn) - new Date(a.createdOn) })).map(data=> ({
_id: data._id,
credit:data.type=='Credit'? data.amount:null,
debit:data.type=='Debit'? data.amount:null,
amount:data.amount,
createdOn:data.createdOn,
type:data.type,
walletId:data.walletId,
}))
}
现在我需要在每个新映射的对象中添加期初余额,这是每个对象的所有先前金额的加法,使用简单的 For 循环我可以激活它,但有没有更好的方法来使用 Reduce 和 Map 来做到这一点?
期望的结果:
[
{
_id: 6,
credit: null,
debit: 897.46,
amount: 897.46,
createdOn: '2020-01-24T10:33:27.000Z',
type: 'Debit',
walletId: 2,
openingBalance: 897.46
},
{
_id: 3,
credit: 624.22,
debit: null,
amount: 624.22,
createdOn: '2020-01-01T15:21:58.000Z',
type: 'Credit',
walletId: 2,
openingBalance: 1521.68
},
{
_id: 8,
credit: -934.81,
debit: null,
amount: -934.81,
createdOn: '2019-12-06T22:17:35.000Z',
type: 'Credit',
walletId: 2,
openingBalance: 586.87
}
]
解决方案
我建议生成一组类似钱包的对象,每个对象都有一个transactions
属性,具有您描述的数组。
但是请注意,openBalance
应该以相反的方向总结,即从较旧的交易到最近的交易。
我也会只执行一次排序操作,然后使用 aMap
来收集正确钱包transaction
列表中的数据。
这是您可以使用的代码。作为奖励,它还在扩展钱包对象级别注册当前余额:
let wallets = [{ title: "Wallet 1", _id: "1", created: new Date("2020-07-14T00:00:00.000Z") },{ title: "Wallet 2", _id: "2", created: new Date("2020-07-13T00:00:00.000Z") },{ title: "Wallet 3", _id: "3", created: new Date("2020-07-19T00:00:00.000Z") }]
let tcode = [{ "createdOn": "2020-03-16T11:58:52.000Z", "type": "Credit", "_id": 2, "amount": 212.92, walletId: 1 },{ "createdOn": "2020-01-01T15:21:58.000Z", "type": "Credit", "_id": 3, "amount": 624.22, walletId: 2 },{ "createdOn": "2019-12-13T20:50:38.000Z", "type": "Credit", "_id": 4, "amount": -874.15, walletId: 3 },{ "createdOn": "2020-05-25T22:37:20.000Z", "type": "Credit", "_id": 5, "amount": -502.68, walletId: 1 },{ "createdOn": "2020-01-24T10:33:27.000Z", "type": "Debit", "_id": 6, "amount": 897.46, walletId: 2 },{ "createdOn": "2019-09-24T00:45:15.000Z", "type": "Debit", "_id": 7, "amount": 981.36, walletId: 1 },{ "createdOn": "2019-12-06T22:17:35.000Z", "type": "Credit", "_id": 8, "amount": -934.81, walletId: 2 },{ "createdOn": "2019-09-06T03:49:31.000Z", "type": "Credit", "_id": 9, "amount": 818.77, walletId: 3 },{ "createdOn": "2020-04-23T22:09:46.000Z", "type": "Credit", "_id": 10, "amount": 312.33, walletId: 3 },{ "createdOn": "2020-07-18T09:15:12.000Z", "type": "Credit", "_id": 11, "amount": -739.77, walletId: 1 }];
// Key the wallets by their id, and add a list of transactions for them
let map = new Map(wallets.map(wallet => [+wallet._id, ({...wallet, ...{ transactions: [], openBalance: 0 }})]));
// Get a sorted copy of the transactions
let sorted = [...tcode].sort((a, b) => a.createdOn.localeCompare(b.createdOn));
// Put each transaction in the corresponding wallet's list
for (let { createdOn, type, _id, amount, walletId } of sorted) {
let wallet = map.get(+walletId); // pick up the corresponding wallet
// Avoid floating point inaccuracies
wallet.openBalance = +(wallet.openBalance + amount).toFixed(2);
wallet.transactions.unshift({
_id,
credit: type == "Credit" ? amount : null,
debit: type == "Dedit" ? amount : null,
amount,
createdOn,
type,
walletId,
openBalance: wallet.openBalance
});
}
// Extract the result from the map
let richWallets = Array.from(map.values());
console.log(richWallets);
以上还解决了添加小数时浮点精度问题的潜在问题。
由于 JavaScript 中缺少适当的小数类型,将金额存储为美分实际上是一种好习惯,因此它们始终是整数。然后将表示以适当的货币留给表示层,表示层会将金额除以 100。
推荐阅读
- python - 如何循环生成变量名?
- javascript - Visual Studio Code 为 jest describe 添加了 yargs 要求
- python - 如何从 python-telegram-bot 中的 inlinekeybord 获取结果
- couchbase - couchbase 我正在做的是将索引设置在正确的位置吗?
- c++ - 如何捕捉 EM_SHOWBALLOONTIP CEdit 消息?
- angular - 如何在ag网格角度中使用多个标题
- cloud - Cloudwatch 报警角色权限
- python - opencv中亮度和对比度的单位测量
- discord.py - Discord.py 踢出服务器的所有成员
- swift - Swift - 如何使用键盘快捷键将 Touch Bar 置于最前面