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

Javascript remove duplicate in a list of objects merging some properties

我有这个列表:

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"
   }
];

谁能帮帮我?谢谢

使用 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)

您可以使用 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);

如果您对使用 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. 对于每个debtor/creditor组,合并数量
  3. 将每个 debtor/creditor 组提取到一个数组中

第一步:groupBy(groupKey)

第一步获取原始debts数组

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

第 2 步:地图(减少(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"
    }
]