javascript - 分组并计算 Javascript 数组中属性的平均值/平均值
问题描述
我很难找到我在其他 stackoverflow 帖子中寻找的解决方案,尽管我强烈地觉得它必须存在。如果是这样,请朝着正确的方向前进。
我正在尝试使用体育数据在 javascript 中做一个非常标准的组。我有以下对象数组:
const myData = [
{team: "GSW", pts: 120, ast: 18, reb: 11},
{team: "GSW", pts: 125, ast: 28, reb: 18},
{team: "GSW", pts: 110, ast: 35, reb: 47},
{team: "HOU", pts: 100, ast: 17, reb: 43},
{team: "HOU", pts: 102, ast: 14, reb: 32},
{team: "SAS", pts: 127, ast: 21, reb: 25},
{team: "SAS", pts: 135, ast: 25, reb: 37},
{team: "SAS", pts: 142, ast: 18, reb: 27}
]
我数据中的每一行对应于特定篮球比赛的结果。简而言之,我想按数据分组,并对分组数据应用平均值/平均值函数。我期望的结果是:
const groupedData = [
{team: "GSW", pts: 118.3, ast: 27.0, reb: 25.3},
{team: "HOU", pts: 101, ast: 15.5, reb: 37.5},
{team: "SAS", pts: 134.7, ast: 21.3, reb: 29.7}
]
我更喜欢在这里使用带有 reduce() 的 vanilla javascript ...鉴于我对 reduce 的了解,这似乎是最好的方法。我目前正在为此工作,如果我能在其他人发布答案之前让它工作,我会发布。
编辑:我的实际数据有约 30 个键。我希望找到一个解决方案,它只要求我(a)仅指定要分组的团队列,并假设它对其余列进行分组,或者(b)传递一个统计列数组(pts、asts等)。 ) 而不是为每个统计数据创建一行。
谢谢!
解决方案
一种方法是结合使用reduce
和map
。
const myData = [
{team: "GSW", pts: 120, ast: 18, reb: 11},
{team: "GSW", pts: 125, ast: 28, reb: 18},
{team: "GSW", pts: 110, ast: 35, reb: 47},
{team: "HOU", pts: 100, ast: 17, reb: 43},
{team: "HOU", pts: 102, ast: 14, reb: 32},
{team: "SAS", pts: 127, ast: 21, reb: 25},
{team: "SAS", pts: 135, ast: 25, reb: 37},
{team: "SAS", pts: 142, ast: 18, reb: 27}
]
// Calculate the sums and group data (while tracking count)
const reduced = myData.reduce(function(m, d){
if(!m[d.team]){
m[d.team] = {...d, count: 1};
return m;
}
m[d.team].pts += d.pts;
m[d.team].ast += d.ast;
m[d.team].reb += d.reb;
m[d.team].count += 1;
return m;
},{});
// Create new array from grouped data and compute the average
const result = Object.keys(reduced).map(function(k){
const item = reduced[k];
return {
team: item.team,
ast: item.ast/item.count,
pts: item.pts/item.count,
reb: item.reb/item.count
}
})
console.log(JSON.stringify(result,null,4));
编辑:刚刚看到您对问题的更新。如果您可以白名单(提供要计算的键数组)或黑名单(提供要忽略的键数组)键以编程方式执行此操作,则可以取消每个键的每一行。
const myData = [
{team: "GSW", pts: 120, ast: 18, reb: 11},
{team: "GSW", pts: 125, ast: 28, reb: 18},
{team: "GSW", pts: 110, ast: 35, reb: 47},
{team: "HOU", pts: 100, ast: 17, reb: 43},
{team: "HOU", pts: 102, ast: 14, reb: 32},
{team: "SAS", pts: 127, ast: 21, reb: 25},
{team: "SAS", pts: 135, ast: 25, reb: 37},
{team: "SAS", pts: 142, ast: 18, reb: 27}
]
/**
* Function which accepts a data array and a list of whitelisted
* keys to find the average of each key after grouping
*/
function getGroupedData(data, whitelist) {
// Calculate the sums and group data (while tracking count)
const reduced = data.reduce(function(m, d) {
if (!m[d.team]) {
m[d.team] = { ...d,
count: 1
};
return m;
}
whitelist.forEach(function(key) {
m[d.team][key] += d[key];
});
m[d.team].count += 1;
return m;
}, {});
// Create new array from grouped data and compute the average
return Object.keys(reduced).map(function(k) {
const item = reduced[k];
const itemAverage = whitelist.reduce(function(m, key) {
m[key] = item[key] / item.count;
return m;
}, {})
return {
...item, // Preserve any non white-listed keys
...itemAverage // Add computed averege for whitelisted keys
}
})
}
console.log(JSON.stringify(getGroupedData(myData, ['pts', 'ast', 'reb']), null, 4));
推荐阅读
- vb.net - Chrome DevTools SetTimeZoneOverRideCommand 无法更改系统时间
- php - 使用 PHP 通过 cURL 发送的电子邮件中的空字段
- sql - 当有唯一值但有重复值时,我如何计数,计数保持不变
- video-streaming - 如何从流式视频中录制音频和视频?
- git - 如何在不提交固定更改的情况下修复 linting 错误?
- r - 如何在 r 中删除我的三元图中的 xy 网格线
- python - 如何使用 Python openpyxl 在 excel 中映射数据
- javascript - 这个函数构造(函数返回函数)是什么意思?
- python - 在可用的非空键上加入 pandas DataFrames
- git - 通过 unix manager:如何检索 gpg 密钥