基于数组索引递增Map值的函数问题排查与优化建议
问题描述
现有数组arr1:
const arr1 = [ "Strongly positive", "Positive", "Neutral", "Negative", "Strongly negative" ];
以及响应对象responses:
const responses = [ { values: { QID16: 3 } }, { values: { QID16: ["1", "2", "3"] } }, { values: { QID16: 1 } } ];
需求是创建一个返回Map的函数:
- Map的键为
arr1的元素 - 值为该元素对应的
index+1在responses中出现的次数 - 示例:
responses[0].values.QID16为3,对应arr1中索引2的Neutral
当前编写的getCounts函数可处理数值类型的响应值,但无法正确处理数组类型的响应值,需排查错误并提供简化方案。函数代码如下:
function getCounts(mainId, choices, responses) { let choicesCounts = new Map(); choices.forEach((choice, i) => { choicesCounts.set(choice, 0); const id = i + 1; responses.forEach((response) => { if (response.values[mainId] && response.values[mainId] === id) { choicesCounts.set(choice, choicesCounts.get(choice) + 1); } if ( response.values[mainId] && Array.isArray(response.values[mainId]) && response.values[mainId].includes(id.toString()) ) { // 此处存在问题 response.values[mainId].forEach((n) => { choicesCounts.set( choices.at(parseInt(n, 10) - 1), choicesCounts.get(choices.at(parseInt(n, 10) - 1)) + 1 ); }); } }); }); return choicesCounts; }
调用方式:
console.log(getCounts("QID16", arr1, responses));
期望输出(实际为Map,以下用对象形式展示结构):
// 注:实际输出是Map,不是对象 const desiredOutput = { "Strongly positive": 2, // 数字1在responses中出现2次 Positive: 1, // 数字2在responses中出现1次 Neutral: 2, Negative: 0, "Strongly negative": 0 };
错误排查与简化方案
原函数问题分析
- 重复计数:遍历每个选项时,只要数组响应包含当前id,就会遍历整个数组给对应选项计数,导致同一个数组响应被多次处理。比如
["1","2","3"]会在处理Strongly positive(id=1)、Positive(id=2)、Neutral(id=3)时各被遍历一次,最终计数重复累加。 - 类型不匹配:数值类型的id是数字,而数组中的值是字符串,直接用
===比较会不匹配(如1 === "1"为false)。
简化实现方案
换思路:先统一收集所有有效id(转为数字),统计每个id的出现次数,最后映射到arr1元素生成Map。
function getCounts(mainId, choices, responses) { // 初始化计数Map,所有选项初始值为0 const counts = new Map(choices.map(choice => [choice, 0])); // 遍历所有响应,处理每个响应的id responses.forEach(response => { const value = response.values?.[mainId]; if (!value) return; // 把单个值或数组值统一转为数字数组 const ids = Array.isArray(value) ? value.map(n => parseInt(n, 10)) : [parseInt(value, 10)]; // 对每个id对应的选项计数+1 ids.forEach(id => { const choice = choices[id - 1]; if (choice) { // 过滤无效id counts.set(choice, counts.get(choice) + 1); } }); }); return counts; }
方案说明
- 简洁初始化:用
choices.map直接生成初始键值对,替代循环set操作。 - 统一类型处理:不管响应是单个值还是数组,都转为数字数组,避免重复判断。
- 单次遍历响应:每个响应仅处理一次,不会重复遍历数组响应,避免重复计数。
- 边界防护:判断
choice是否存在,防止无效id导致错误。
调用后得到的Map与期望输出完全一致。
内容的提问来源于stack exchange,提问作者psych0groov3
相关产品推荐
相关产品推荐

