javascript - 从两个类别的 JavaScript 数组计算总计和小计

标签 javascript arrays ecmascript-6 javascript-objects

我正在尝试使用 Array.prototype.reduce< 将三个总数相加:totalPointsmonthlyTotalsmonthlyByType/.

我有 totalPointsmonthlyTotals 效果很好,但我卡在最后一个 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/

相关文章:

javascript - ES6 导入扩展类

javascript - 使用 Canvas 旋转坐标(面部地标),原点位于左上角

php - 从关联数组中获取值

javascript - Google API 错误,但仍然有效

php - 使用 codeigniter 和 mysql 回显图像数组

Java从字符串数组中随机生成字符串值

javascript - Array .prototype .filter() 在什么时候检查虚假值?

javascript - onClick 改变子组件 ReactJS 的状态

javascript - React Native NativeModules 在一个对象中传递多个函数

javascript - Chart.js ajax推送另一个数据集总是 "undefined"