【问题标题】:How to reduce and map an object array?如何减少和映射对象数组?
【发布时间】:2017-10-11 22:36:59
【问题描述】:

如何减少这个对象数组并将其映射到一个新数组?

我的数据:

var objArray = 
  [{
    state: 'NY',
    type: 'A',
    population: 100
  },
  {
    state: 'NY',
    type: 'A',
    population: 300
  },
  {
    state: 'NY',
    type: 'B',
    population: 200
  },
  {
    state: 'CA',
    type: 'A',
    population: 400
  },
  {
    state: 'CA',
    type: 'A',
    population: 400
  }];

如果一个条目具有相同的statetype,我需要将它组合成一个条目并将它们的人口相加。

最后我需要把它映射成这种格式的数组。

 var outputArray = [ ['A', 'NY', 400 ], ['B', 'NY', 200], ['A', 'CA', 800] ]

【问题讨论】:

  • 您需要展示您尝试过的内容。 Stackoverflow 不是免费的代码编写或教程服务。这里的目标是帮助您修复您的代码

标签: javascript arrays


【解决方案1】:

嗯,首先你要减少它。这可以像这样完成......

objArray.reduce((prev, obj) => {
    if(1 + (indx = prev.findIndex(oldObj => oldObj.type === obj.type && oldObj.state === obj.state))) {
        prev[indx].population += obj.population;
    } else {
        prev.push({...obj})
    }
    return prev;
}, [])

这将获取正在收集的数组,并以某种方式对其进行修改并在 reduce 回调中返回它。如果可以找到具有正确状态和类型的值,它将修改现有值的总体;或者它会将一个新对象附加到数组的末尾。

现在你需要映射它。

.map(obj => [ obj.type, obj.state, obj.population ])

【讨论】:

  • 注意,这段代码也改变了原始数组
  • 它变异了prev,但每次迭代都不同,并且是故意变异的。我不认为objArray 是——对吧?
  • console.log(objArray) - 你会看到它改变了项目 0 和 3 中的人口
  • 你推送obj - 对象是通过引用传递的 - 所以,当你更新prev[0].population 时,它与objArray[0] 是同一个对象,所以objArray[0].population 是与prev[0].population 相同的属性
  • @jm22 当你在 JS 对象字面量中放置一个没有值的键时,它是 obj: obj 的简写,即推动自身。您必须使用传播操作来推送其内容,而不是本身
【解决方案2】:

我建议使用lodash 包(它是Javascript 应用程序中极为常见的包)。它为操作数组添加了许多很棒的功能。 This post 解释了如何对组中的值求和。您需要稍微修改此答案以考虑您的两个参数,您可以通过将groupBy 命令更改为:

_.groupBy(objArray, function(val){
    return val.state + "#" + val.type
})

【讨论】:

    【解决方案3】:

    你可以试试这样的:

    var arr = Object.keys(objArray).map(function (key) { return Object.keys(objArray[key]).map(function (key) { return [[objArray[0].state, objArray[0].type, objArray[0].population],[objArray[1].state, objArray[1].type, objArray[1].population]]}); })[0][0];
    

    【讨论】:

      【解决方案4】:

      如果您知道状态和类型永远不会有特定字符(例如“_”),您可以从 statetype 中创建一个键,例如“NY_A” - 有点像数据库中的复合键。然后,您只需使用这些键创建一个对象,添加种群,然后将它们拉到一个数组中:

      Object.entries(
          objArray.reduce((acc,curr) => (
          acc[curr.type + '_' + curr.state] = curr.population + (acc[curr.type + '_' + curr.state] || 0)
          , acc), {}))
      .map(item => [...item[0].split('_'), item[1]])
      

      【讨论】:

        【解决方案5】:
        const _ = require('lodash')
        
        const input = [
          { state: 'NY', type: 'A', population: 100 },
          { state: 'NY', type: 'A', population: 300 },
          { state: 'NY', type: 'B', population: 200 },
          { state: 'CA', type: 'A', population: 400 },
          { state: 'CA', type: 'A', population: 400 }
        ]
        
        const expected = [
          ['A', 'NY', 400],
          ['B', 'NY', 200],
          ['A', 'CA', 800]
        ]
        
        const output = _(input)
          .groupBy(({ state, type }) => [state, type].join(':'))
          .mapValues((states) => states.reduce((total, { population }) => total + population, 0))
          .map((population, stateType) => {
            const [state, type] = stateType.split(':')
            return [type, state, population]
          })
          .value()
        
        console.log(expected)
        console.log(output)
        

        【讨论】:

          猜你喜欢
          • 2019-02-09
          • 2018-01-28
          • 2018-03-21
          • 2016-03-04
          • 1970-01-01
          • 2012-03-09
          • 1970-01-01
          • 2023-04-03
          • 1970-01-01
          相关资源
          最近更新 更多