整理对象的javascript数组

时间:2018-07-19 20:12:15

标签: javascript data-manipulation

很难确定我正在处理的特定数据操作,所以请原谅标题不佳-我将举一个很好的例子。我有以下对象的javascript数组,其中包含一些体育数据:

[
    { team: "Knicks", assists: 24 }, 
    { team: "Knicks", assists: 12 }, 
    { team: "Knicks", assists: 17 }, 
    { team: "Knicks", assists: 19 }, 
    { team: "Warriors", assists: 31 }, 
    { team: "Warriors", assists: 25 }, 
    { team: "Warriors", assists: 20 }, 
    { team: "Spurs", assists: 15 }, 
    { team: "Spurs", assists: 17 }, 
    { team: "Spurs", assists: 32 }, 
    { team: "Spurs", assists: 12 }, 
    { team: "Spurs", assists: 18 }
]

,并希望整理一下以便数据看起来像这样:

[
    { team: "Knicks", assists: [24, 36, 53, 72] },
    { team: "Warriors", assists: [31, 56, 76] },
    { team: "Spurs", assists: [15, 32, 64, 76, 94] }

]

原始对象阵列中的每个唯一团队都会在新阵列中接收其自己的对象,并且辅助值现在是辅助值的累积总和。我可以肯定,总是会以正确的方式对对象的原始数组进行排序,这样,从上到下循环将产生正确的累积总和。

对此非常感谢,谢谢!

4 个答案:

答案 0 :(得分:3)

您可以使用reduce方法构建对象,然后使用Object.values方法获取对象数组。

const data = [{"team":"Knicks","assists":24},{"team":"Knicks","assists":12},{"team":"Knicks","assists":17},{"team":"Knicks","assists":19},{"team":"Warriors","assists":31},{"team":"Warriors","assists":25},{"team":"Warriors","assists":20},{"team":"Spurs","assists":15},{"team":"Spurs","assists":17},{"team":"Spurs","assists":32},{"team":"Spurs","assists":12},{"team":"Spurs","assists":18}]

const result = data.reduce((r, {team, assists}) => {
  if(!r[team]) r[team] = {team, assists: [assists]}
  else r[team].assists.push(r[team].assists.slice(-1)[0] + assists);
  return r;
}, {})

console.log(Object.values(result))

答案 1 :(得分:2)

这里是使用临时ES6 Map的函数式编程方法:

const teams = [{ team: "Knicks", assists: 24 },{ team: "Knicks", assists: 12 },{ team: "Knicks", assists: 17 },{ team: "Knicks", assists: 19 },{ team: "Warriors", assists: 31 },{ team: "Warriors", assists: 25 },{ team: "Warriors", assists: 20 },{ team: "Spurs", assists: 15 },{ team: "Spurs", assists: 17 },{ team: "Spurs", assists: 32 },{ team: "Spurs", assists: 12 },{ team: "Spurs", assists: 18 }];

const result = Array.from(
    teams.reduce( (acc, {team, assists}) => acc.set(team, (acc.get(team) || []).concat(assists)), new Map),
    ([team, assists]) => ({team, assists})
);

console.log(result);

答案 2 :(得分:1)

您还可以像这样使用array#forEach()方法:

const teams= [
    { team: "Knicks", assists: 24 }, 
    { team: "Knicks", assists: 12 }, 
    { team: "Knicks", assists: 17 }, 
    { team: "Knicks", assists: 19 }, 
    { team: "Warriors", assists: 31 }, 
    { team: "Warriors", assists: 25 }, 
    { team: "Warriors", assists: 20 }, 
    { team: "Spurs", assists: 15 }, 
    { team: "Spurs", assists: 17 }, 
    { team: "Spurs", assists: 32 }, 
    { team: "Spurs", assists: 12 }, 
    { team: "Spurs", assists: 18 }
]

let teamGroup = {}

teams.forEach(team => {
  teamGroup[team.team] ? // check if that array exists or not in teamgroup object
    teamGroup[team.team].push(team.assists)  // just push
   : (teamGroup[team.team] = [], teamGroup[team.team].push(team.assists)) // create a new array and push
})

console.log(teamGroup);

答案 3 :(得分:1)

lodash库中有一个方便的_.groupBy,可以为您完成很多工作。

如果您执行const groups = _.groupBy(data, team),则会得到:

{
    "Knicks": [
        { "team": "Knicks", "assists": 24},
        { "team": "Knicks", "assists": 12},
        { "team": "Knicks", "assists": 17},
        { "team": "Knicks", "assists": 19},
    ],
    // ...
}

然后

const result = _.map(groups, (teamData, teamName) => {
    // Convert teamData array into a single record
    const assists = _.map(teamData, "assists"); // e.g. [24, 12, 17, 19]
    return { team: teamName, assists: runningTotal(assists) };
});

// Turns an array like [1,2,3,4] into an array like [1,3,6,10]
function runningTotal(array) {
    let prev = 0;
    return array.map(next => {
        prev = next + prev;
        return prev;
    });
}

这给出了预期的结果。


这种方法并不比使用reduce的解决方案短很多,但是我个人认为groupBymap之类的高阶运算比{ {1}}。 (但是,当然,这需要lodash或类似实现的reduce函数)


编辑:我完全错过了助攻不只是一系列助攻,而是一连串的总成绩。对此做了一点说明。该代码比reduce解决方案要长得多,但是IMO更加清晰。