[英]Calculate total and subtotals from JavaScript array on two categories
我正在嘗試使用Array.prototype.reduce
將三個總數totalPoints
: totalPoints
, monthlyTotals
和monthlyByType
。
我有totalPoints
,和monthlyTotals
都totalPoints
,但是我被困在最后一個, 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,
},
]
這是我的減速器:
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
對象的一些進一步說明:
使用{ ...Array(12).fill(0) }
或Object.assign({}, Array(12).fill(0) )
創建monthlyTotals
屬性。 這將創建一個對象,該數組的索引作為鍵,而value作為鍵的值
monthByType
需要填充對象文字。 您可以Array.from()
使用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))
您可以采用預填充數組而不是對象,然后分配或添加值。
const getYear = fn => Array.from({ length: 12 }, fn); var data = [{ 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 }], result = data.reduce((r, { gameType, gameMonth, gamePoints }) => { r.total += gamePoints; r.monthlyTotals[gameMonth] += gamePoints; r.monthByType[gameMonth][gameType] = (r.monthByType[gameMonth][gameType] || 0) + gamePoints; return r; }, { total: 0, monthlyTotals: getYear(() => 0), monthByType: getYear(() => ({ })) }); console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.