首页 > 解决方案 > 在嵌套对象数组中,如何访问先前的对象值并增加一个 fileld

问题描述

我有两个对象数组

  1. 钱包
      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") }]
  1. 交易
    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
  }
]

标签: javascripttypescript

解决方案


我建议生成一组类似钱包的对象,每个对象都有一个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。


推荐阅读