JavaScript按对象属性分组统计另一属性值出现次数的通用实现
优化方案
你可以通过动态生成计数对象的方式完全去掉硬编码逻辑,不需要为每个属性单独声明计数变量,也不需要switch分支,properties数组的长度和取值变化时不需要修改函数逻辑。
最小改动优化(基于你原有逻辑调整)
function doClick() { let countArray = []; for (let i = 0; i < years.length; i++) { let currentYear = years[i]; // 动态初始化计数对象,所有属性默认值为0 let countObj = Object.fromEntries(properties.map(prop => [prop, 0])); for (let x = 0; x < properties.length; x++) { let currentProperty = properties[x]; for (let z = 0; z < myArray.length; z++) { if (myArray[z].date === currentYear && myArray[z].prop1 === currentProperty) { // 直接通过属性名访问累加,无需switch countObj[currentProperty]++; } } } countArray.push({ year: currentYear, ...countObj }); } console.log(countArray); }
注:如果需要兼容ES2019以下的运行环境,可以把
Object.fromEntries生成计数对象的逻辑替换为循环初始化:let countObj = {}; properties.forEach(prop => countObj[prop] = 0);
更高效率优化(适合数据量较大的场景)
原有三层循环时间复杂度较高,你可以先遍历一次源数据做预聚合,再按年份生成结果,性能提升明显:
function doClick() { // 先预统计所有[年份-属性]的出现次数 const statMap = {}; myArray.forEach(item => { const year = item.date; const prop = item.prop1; if (!statMap[year]) { statMap[year] = {}; properties.forEach(p => statMap[year][p] = 0); } // 只统计properties中存在的属性 if (properties.includes(prop)) statMap[year][prop]++; }); // 按给定的years数组顺序生成结果,确保没有数据的年份也会生成全属性为0的条目 const countArray = years.map(year => { const defaultCount = {}; properties.forEach(p => defaultCount[p] = 0); return { year, ...(statMap[year] || defaultCount) } }); console.log(countArray); }
两种方案输出的结果都和你原来的运行结果完全一致,且properties数组扩容、修改取值时都不需要调整函数内部逻辑。
内容的提问来源于stack exchange,提问作者Kevin
相关产品推荐
相关产品推荐

