我正在尝试使用 Array.prototype.reduce< 将三个总数相加:
.totalPoints
、monthlyTotals
和 monthlyByType
/
我有 totalPoints
和 monthlyTotals
效果很好,但我卡在最后一个 monthlyByType
上。
这是我需要迭代的数组:
const gamePointsArray = [
{
gamePlayId: 'ggg1',
gameType: 1,
gameMonth: 4,
gamePoints: 4000,
},
{
gamePlayId: 'ggg2',
gameType: 2,
gameMonth: 2,
gamePoints: 7000,
},
{
gamePlayId: 'ggg3',
gameType: 2,
gameMonth: 0,
gamePoints: 3000,
},
{
gamePlayId: 'ggg4',
gameType: 1,
gameMonth: 8,
gamePoints: 25000,
},
{
gamePlayId: 'ggg5',
gameType: 3,
gameMonth: 8,
gamePoints: 5000,
},
{
gamePlayId: 'ggg6',
gameType: 3,
gameMonth: 3,
gamePoints: 10000,
},
{
gamePlayId: 'ggg7',
gameType: 2,
gameMonth: 3,
gamePoints: 5000,
},
]
这是我的 reducer :
const gamePointsReducer = (acc, game) => {
const { gamePlayId, gameType, gameMonth, gamePoints,} = game
if (!acc['totalPoints']) {
acc['totalPoints'] = gamePoints
} else {
acc['totalPoints'] += gamePoints
}
if (!acc['monthlyTotals']) {
acc['monthlyTotals'] = {
0: 0,
1: 0,
2: 0,
3: 0,
4: 0,
5: 0,
6: 0,
7: 0,
8: 0,
9: 0,
10: 0,
11: 0,
}
}
acc.monthlyTotals[`${gameMonth}`] += gamePoints
if (!acc['monthByType']) {
acc['monthByType'] = {
0: {},
1: {},
2: {},
3: {},
4: {},
5: {},
6: {},
7: {},
8: {},
9: {},
10: {},
11: {},
}
}
acc.monthByType[`${gameMonth}`] += {
[`${gameType}`]: gamePoints
}
return acc
}
const monthTotalsObj = gamePointsArray.reduce(gamePointsReducer, {})
console.log('Game Points totals obj', monthTotalsObj);
我需要最终结果 Object
看起来像这样:
{
totalPoints: 59000,
monthlyTotals: {
0: 3000,
1: 0,
2: 7000,
3: 15000,
4: 4000,
5: 0,
6: 0,
7: 0,
8: 30000,
9: 0,
10: 0,
11: 0,
},
monthByType: {
0: {
2: 3000,
},
1: {},
2: {
2: 7000,
},
3: {},
4: {
1: 4000,
},
5: {},
6: {},
7: {},
8: {
1: 25000,
3: 5000,
},
9: {},
10: {},
11: {},
}
}
最佳答案
您可以创建一个默认的 intialValue
对象。这将帮助您避免在整个 reduce 回调中进行 if
检查。
然后 reduce
回调类似于您已经在做的事情。只需更新每个 monthByType
const gamePointsArray=[{gamePlayId:"ggg1",gameType:1,gameMonth:4,gamePoints:4000,},{gamePlayId:"ggg2",gameType:2,gameMonth:2,gamePoints:7000,},{gamePlayId:"ggg3",gameType:2,gameMonth:0,gamePoints:3000,},{gamePlayId:"ggg4",gameType:1,gameMonth:8,gamePoints:25000,},{gamePlayId:"ggg5",gameType:3,gameMonth:8,gamePoints:5000,},{gamePlayId:"ggg6",gameType:3,gameMonth:3,gamePoints:10000,},{gamePlayId:"ggg7",gameType:2,gameMonth:3,gamePoints:5000,}];
const initialValue = {
totalPoints: 0,
monthlyTotals: { ...Array(12).fill(0) },
monthByType: { ... Array.from({ length: 12 }, _ => ({})) }
}
const output = gamePointsArray.reduce((acc, o) => {
acc.totalPoints += o.gamePoints;
acc.monthlyTotals[o.gameMonth] += o.gamePoints;
acc.monthByType[o.gameMonth][o.gameType] =
(acc.monthByType[o.gameMonth][o.gameType] || 0) + o.gamePoints;
return acc;
}, initialValue)
console.log(output)
下面是对 initialValue
对象的进一步解释:
monthlyTotals
属性是使用 { ...Array(12).fill(0) }
或 Object.assign({}, Array( 12).填充(0))
。这将创建一个对象,该对象以数组的索引作为键,以值作为键的值
monthByType
需要用对象字面量填充。您可以使用 Array.from()
为了这。 (您不能像上面那样使用 fill
。它会在每个索引中使用相同的静态对象引用,这是不可取的)
const arrayWithZeros = Array(12).fill(0),
monthlyTotals = { ...arrayWithZeros };
const arrayWithEmptyLiterals = Array.from({ length: 12 }, _ => ({}) ),
monthByType = { ...arrayWithEmptyLiterals }
console.log(JSON.stringify(arrayWithZeros))
console.log(JSON.stringify(monthlyTotals))
console.log(JSON.stringify(arrayWithEmptyLiterals))
console.log(JSON.stringify(monthByType))
关于javascript - 从两个类别的 JavaScript 数组计算总计和小计,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57339633/