Javascript删除合并某些属性的对象列表中的重复项

时间:2018-11-19 09:50:13

标签: javascript arrays lodash ramda.js

我有这个列表:

const debts = [
  {
    amount: 10,
    debtor: "Mark",
    creditor: "John"
  },
  {
    amount: 20,
    debtor: "Mark",
    creditor: "John"
  },
  {
    amount: 10,
    debtor: "Mark",
    creditor: "Tom"
   }
];

...并且我想合并具有相同债务人和债权人的元素,以计算总金额,就像这样

const debts = [
  {
    amount: 30, // 10 + 20
    debtor: "Mark",
    creditor: "John"
  },
  {
    amount: 10,
    debtor: "Mark",
    creditor: "Tom"
   }
];

有人可以帮助我吗?谢谢

3 个答案:

答案 0 :(得分:5)

如果您对使用Ramda的解决方案感兴趣,请参考以下建议:

const {
  pipe,
  mergeWithKey,
  map,
  reduce,
  values,
  groupBy,
  props,
  join
} = R;

const debts = [{
    amount: 10,
    debtor: "Mark",
    creditor: "John"
  },
  {
    amount: 20,
    debtor: "Mark",
    creditor: "John"
  },
  {
    amount: 10,
    debtor: "Mark",
    creditor: "Tom"
  }
];

const mergeAmount = mergeWithKey((key, left, right) => key === 'amount' ? left + right : left);
const groupKey = pipe(props(['debtor', 'creditor']), join(' ~> '));

const process =
  pipe(
    groupBy(groupKey),
    map(reduce(mergeAmount, {})),
    values);

console.log(process(debts));
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>


想法是将过程分为三个步骤:

  1. 将债务人和债权人组合在一起
  2. 对于每个债务人/债权人组,合并金额
  3. 将每个债务人/债权人组提取到一个数组中

步骤1:groupBy(groupKey)

步骤1获取原始的debts数组

{
    "Mark ~> John": [
        {
            amount: 10,
            creditor: "John",
            debtor: "Mark"
        },
        {
            amount: 20,
            creditor: "John",
            debtor: "Mark"
        }
    ],
    "Mark ~> Tom": [
        {
            amount: 10,
            creditor: "Tom",
            debtor: "Mark"
        }
    ]
}

步骤2:map(reduce(mergeAmount,{}))

第2步从第1步获取输出

{
    "Mark ~> John": {
        amount: 30,
        creditor: "John",
        debtor: "Mark"
    },
    "Mark ~> Tom": {
        amount: 10,
        creditor: "Tom",
        debtor: "Mark"
    }
}

第3步:值

第3步从第2步获取输出

[
    {
        amount: 30,
        creditor: "John",
        debtor: "Mark"
    },
    {
        amount: 10,
        creditor: "Tom",
        debtor: "Mark"
    }
]

答案 1 :(得分:2)

您可以使用Array.reduce创建一个对象,其键作为唯一的一对债务人和债权人对,而值作为结果对象。如果对象中存在该对的现有条目,则增加数量,否则在对象中添加一个新条目。

最后,使用Object.values收集所有对象。

let debts = [{amount: 10,debtor: "Mark",creditor: "John"},{amount: 20,debtor: "Mark",creditor: "John"},{amount: 10,debtor: "Mark",creditor: "Tom"}];

let result = Object.values(debts.reduce((a,c) => {
  let key = `${c.debtor}~~${c.creditor}`;
  if(a[key]) a[key].amount += c.amount;
  else a[key] = Object.assign({},c);
  return a;
}, {}));
console.log(result);

答案 2 :(得分:1)

使用filter()函数遍历结果列表,并检查债务人-债权人对是否已经存在。如果存在,则更新金额。否则,将其添加为结果列表中的新条目。

const debts = [
  {
    amount: 10,
    debtor: "Mark",
    creditor: "John"
  },
  {
    amount: 20,
    debtor: "Mark",
    creditor: "John"
  },
  {
    amount: 10,
    debtor: "Mark",
    creditor: "Tom"
  }
];

var result = []
debts.forEach((item) => {
  var existing = result.filter((resultItem, index) => {
    return resultItem.debtor === item.debtor && resultItem.creditor === item.creditor;
  });

  if (existing.length) {
    var existingIndex = result.indexOf(existing[0]);
    result[existingIndex].amount += item.amount;
  } else {
    result.push(item);
  }
})

console.log(result)