首页 > 解决方案 > 如何基于对象数组中的相似值(不是属性)对对象数组执行加/减运算

问题描述

我有一个这样的对象数组:

i/p:

let payments=[ 
  {from:"b",to:"c",amount:30}, {from:"a",to:"c",amount:30},
  {from:"c",to:"a",amount:50}, {from:"b",to:"a",amount:50},
  {from:"c",to:"b",amount:66.66}, {from:"a",to:"b",amount:66.66},
  {from:"a",to:"c",amount:150}, {from:"b",to:"c",amount:150}, 
  {from:"a", to:"c",amount:75}, {from:"b", to:"c",amount:125} 
]

现在我想基于相同的属性值对金额属性执行求和运算,并基于反向匹配属性值(即从,到)对金额属性进行减法运算,将数组减少为:

o/p:

[
  { from: "b", to: "c", amount: 238.34 }, //(sum of all b->c amounts) minus (sum of all c->b amounts)
  { from: "a", to: "c", amount: 205 },    //(sum of all a->c amounts) minus (sum of all c-a amounts)
  { from: "a", to: "b", amount: 16.66 },  //(sum of all a->b amounts) minus (sum of all b->a amounts)
];

注意:结果数组数量属性不应为负

我尝试了一些方法,但无法实现这一点。任何帮助,将不胜感激。谢谢

标签: javascriptobjectjavascript-objectsdynamic-arrays

解决方案


也许这会有所帮助:

let payments=[ 
  {from:"b",to:"c",amount:30}, {from:"a",to:"c",amount:30},
  {from:"c",to:"a",amount:50}, {from:"b",to:"a",amount:50},
  {from:"c",to:"b",amount:66.66}, {from:"a",to:"b",amount:66.66},
  {from:"a",to:"c",amount:150}, {from:"b",to:"c",amount:150}, 
  {from:"a", to:"c",amount:75}, {from:"b", to:"c",amount:125} 
];

let pay = Object.entries(
  payments.reduce((tot,{from,to,amount})=>{
   let u=from+'-'+to;       // from-to-relationship (in alphabetical order)
   if (to<from) { u=to+'-'+from; amount=-amount }
   tot[u]=(tot[u]||0)+amount;  // collate all payments here
   return tot;
  }, {})
 ).map(([u,a])=>{let ft=u.split('-');
   if (a<0) {ft=ft.reverse();a=-a}
   return {from:ft[0], to:ft[1], amount:a.toFixed(2)}
 })
   
console.log(pay)

.reduce函数中,我将两个合作伙伴之间的所有付款整理到一个以“from-to”命名的“acounts”的帐户对象中,该名称始终按字母顺序建立,因此,如果我遇到付款,{from:"b", to:"a", amount:123}我会交换订单并使金额为负数:

if (to<from) { u=to+'-'+from; amount=-amount }

完成此操作后,我使用 遍历帐户对象Object.entries。这将允许我再次将帐户名称fromto合作伙伴分开。这次我检查,合伙人之间的应付金额是否为负数。如果是这样,我交换合作伙伴的顺序 ( ft) 并将 amonut ( a) 乘以 -1:

if (a<0) {ft=ft.reverse();a=-a}

推荐阅读