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>
想法是将过程分为三个步骤:
- 将债务人和债权人归为一组
- 对于每个debtor/creditor组,合并数量
- 将每个 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"
}
]
我有这个列表:
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>
想法是将过程分为三个步骤:
- 将债务人和债权人归为一组
- 对于每个debtor/creditor组,合并数量
- 将每个 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"
}
]