根据对象级别的公共值减少数组
Reduce array based on common values on object level
我有一个数组,例如
let array = [
{
id: 1,
name: "Name A",
expenseAmount: 100
},
{
id: 1,
name: "Name A",
expenseAmount: 50
},
{
id: 3,
name: "Name B",
expenseAmount: 10
},
{
id: 3,
name: "Name B",
expenseAmount: 20
}
];
我正在寻找一种解决方案,它以这样一种方式压缩该数组,即所有具有相同 ID 和名称的对象都通过它们的费用金额求和,从而导致:
let array_goal = [
{
id: 1,
name: "Name A",
expenseAmount: 150
},
{
id: 3,
name: "Name B",
expenseAmount: 30
}
];
你能帮忙吗?谢谢!
Array.prototype.reduce 是您完成此类任务的朋友。
找一个已经存在的id相同的object加到expense amount中,找不到就自己做加到输出数组中。
let array = [{
id: 1,
name: "Name A",
expenseAmount: 100
},
{
id: 1,
name: "Name A",
expenseAmount: 50
},
{
id: 3,
name: "Name B",
expenseAmount: 10
},
{
id: 3,
name: "Name B",
expenseAmount: 20
}
];
const condenseArray = (arr) => {
return arr.reduce((out, {id, name, expenseAmount}) => {
let data = out.find(({id: _id}) => _id === id);
if (!data) {
const newData = {id, name, expenseAmount: 0};
out = [...out, newData];
data = newData;
}
data.expenseAmount += expenseAmount;
return out;
}, []);
};
console.log(condenseArray(array));
如果为此目的使用库没有问题,您可以使用 lodash
// const _ = require('lodash') // use in source code if not using CDN
let array = [
{
id: 1,
name: "Name A",
expenseAmount: 100
},
{
id: 1,
name: "Name A",
expenseAmount: 50
},
{
id: 3,
name: "Name B",
expenseAmount: 10
},
{
id: 3,
name: "Name B",
expenseAmount: 20
}
];
const ans = _(array)
.groupBy('name')
.map((data, value) => ({
id: data[0].id,
name: data[0].name,
expenseAmount: _.sumBy(data, 'expenseAmount')
}))
.value()
console.log(ans);
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js" integrity="sha256-qXBd/EfAdjOA2FGrGAG+b3YBn2tn5A6bhz+LSgYD96k=" crossorigin="anonymous"></script>
这是一种可能的解决方案:
const mergeIdSumExpenses = (arr = array) => (
Object.values(arr.reduce(
(fin, itm) => ({
...fin,
[itm.id]: {
...itm,
expenseAmount: (fin[itm.id]?.expenseAmount || 0) + itm.expenseAmount
}
}), {}
))
);
说明
- 使用
.reduce
遍历数组并将结果作为对象生成
- 如果当前元素
itm
的 id
已经存在于聚合器中 fin
,
- 然后,将
itm.expenseAmount
添加到现有道具(键:itm.id
)
- 否则,创建一个新道具(键:
itm.id
)
- 最后,使用
Object.values()
仅从结果对象中提取值
代码段
let array = [{
id: 1,
name: "Name A",
expenseAmount: 100
},
{
id: 1,
name: "Name A",
expenseAmount: 50
},
{
id: 3,
name: "Name B",
expenseAmount: 10
},
{
id: 3,
name: "Name B",
expenseAmount: 20
}
];
const mergeIdSumExpenses = (arr = array) => (
Object.values(arr.reduce(
(fin, itm) => ({
...fin,
[itm.id]: {
...itm,
expenseAmount: (fin[itm.id]?.expenseAmount || 0) + itm.expenseAmount
}
}), {}
))
);
console.log(mergeIdSumExpenses());
第一步
Use filter to group by id and name
第二步
const array = [
{id:1,name:"Name A",expenseAmount:100},
{id:1,name:"Name A",expenseAmount:50},
{id:1,name:"Name B",expenseAmount:100},
{id:3,name:"Name B",expenseAmount:10},
{id:3,name:"Name B",expenseAmount:20}
];
const unique = array
.filter((element, index, arr) => index === arr.findIndex(e => e.id == element.id && e.name == element.name))
.map(u => {
u.expenseAmount =
array
.filter(a => a.id == u.id && a.name == u.name)
.reduce((n, {expenseAmount}) => n + expenseAmount, 0);
return u;
});
console.log(unique);
我有一个数组,例如
let array = [
{
id: 1,
name: "Name A",
expenseAmount: 100
},
{
id: 1,
name: "Name A",
expenseAmount: 50
},
{
id: 3,
name: "Name B",
expenseAmount: 10
},
{
id: 3,
name: "Name B",
expenseAmount: 20
}
];
我正在寻找一种解决方案,它以这样一种方式压缩该数组,即所有具有相同 ID 和名称的对象都通过它们的费用金额求和,从而导致:
let array_goal = [
{
id: 1,
name: "Name A",
expenseAmount: 150
},
{
id: 3,
name: "Name B",
expenseAmount: 30
}
];
你能帮忙吗?谢谢!
Array.prototype.reduce 是您完成此类任务的朋友。
找一个已经存在的id相同的object加到expense amount中,找不到就自己做加到输出数组中。
let array = [{
id: 1,
name: "Name A",
expenseAmount: 100
},
{
id: 1,
name: "Name A",
expenseAmount: 50
},
{
id: 3,
name: "Name B",
expenseAmount: 10
},
{
id: 3,
name: "Name B",
expenseAmount: 20
}
];
const condenseArray = (arr) => {
return arr.reduce((out, {id, name, expenseAmount}) => {
let data = out.find(({id: _id}) => _id === id);
if (!data) {
const newData = {id, name, expenseAmount: 0};
out = [...out, newData];
data = newData;
}
data.expenseAmount += expenseAmount;
return out;
}, []);
};
console.log(condenseArray(array));
如果为此目的使用库没有问题,您可以使用 lodash
// const _ = require('lodash') // use in source code if not using CDN
let array = [
{
id: 1,
name: "Name A",
expenseAmount: 100
},
{
id: 1,
name: "Name A",
expenseAmount: 50
},
{
id: 3,
name: "Name B",
expenseAmount: 10
},
{
id: 3,
name: "Name B",
expenseAmount: 20
}
];
const ans = _(array)
.groupBy('name')
.map((data, value) => ({
id: data[0].id,
name: data[0].name,
expenseAmount: _.sumBy(data, 'expenseAmount')
}))
.value()
console.log(ans);
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js" integrity="sha256-qXBd/EfAdjOA2FGrGAG+b3YBn2tn5A6bhz+LSgYD96k=" crossorigin="anonymous"></script>
这是一种可能的解决方案:
const mergeIdSumExpenses = (arr = array) => (
Object.values(arr.reduce(
(fin, itm) => ({
...fin,
[itm.id]: {
...itm,
expenseAmount: (fin[itm.id]?.expenseAmount || 0) + itm.expenseAmount
}
}), {}
))
);
说明
- 使用
.reduce
遍历数组并将结果作为对象生成 - 如果当前元素
itm
的id
已经存在于聚合器中fin
, - 然后,将
itm.expenseAmount
添加到现有道具(键:itm.id
) - 否则,创建一个新道具(键:
itm.id
) - 最后,使用
Object.values()
仅从结果对象中提取值
代码段
let array = [{
id: 1,
name: "Name A",
expenseAmount: 100
},
{
id: 1,
name: "Name A",
expenseAmount: 50
},
{
id: 3,
name: "Name B",
expenseAmount: 10
},
{
id: 3,
name: "Name B",
expenseAmount: 20
}
];
const mergeIdSumExpenses = (arr = array) => (
Object.values(arr.reduce(
(fin, itm) => ({
...fin,
[itm.id]: {
...itm,
expenseAmount: (fin[itm.id]?.expenseAmount || 0) + itm.expenseAmount
}
}), {}
))
);
console.log(mergeIdSumExpenses());
第一步
Use filter to group by id and name
第二步
const array = [
{id:1,name:"Name A",expenseAmount:100},
{id:1,name:"Name A",expenseAmount:50},
{id:1,name:"Name B",expenseAmount:100},
{id:3,name:"Name B",expenseAmount:10},
{id:3,name:"Name B",expenseAmount:20}
];
const unique = array
.filter((element, index, arr) => index === arr.findIndex(e => e.id == element.id && e.name == element.name))
.map(u => {
u.expenseAmount =
array
.filter(a => a.id == u.id && a.name == u.name)
.reduce((n, {expenseAmount}) => n + expenseAmount, 0);
return u;
});
console.log(unique);