很难确定我正在处理的特定数据操作,所以请原谅标题不佳-我将举一个很好的例子。我有以下对象的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] }
]
原始对象阵列中的每个唯一团队都会在新阵列中接收其自己的对象,并且辅助值现在是辅助值的累积总和。我可以肯定,总是会以正确的方式对对象的原始数组进行排序,这样,从上到下循环将产生正确的累积总和。
对此非常感谢,谢谢!
答案 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
的解决方案短很多,但是我个人认为groupBy
和map
之类的高阶运算比{ {1}}。 (但是,当然,这需要lodash或类似实现的reduce
函数)
编辑:我完全错过了助攻不只是一系列助攻,而是一连串的总成绩。对此做了一点说明。该代码比reduce解决方案要长得多,但是IMO更加清晰。