如何从JavaScript数组中提取键与值并分别存入数组
问题需求
需要从给定的JavaScript对象中提取团队名称(Team A、Team B)存入一个数组,同时将对应的任务统计值存入另一个独立数组,且保持团队在原始数据中的顺序。
当前输出数组
[ { "Team A": 2, "Team B": 3 } ]
当前JS代码
var retValue = []; var count = this.jsonArray.map((cv) => { var teams = cv["teams"].reduce((acc, team) => { acc[team["value"]] = team["text"]; return acc; }, {}); return cv["duty"].reduce((acc, duty) => { acc[teams[duty["parentId"]]] = acc[ teams[duty["parentId"]] ] ? acc[teams[duty["parentId"]]] + 1 : 1; return acc; }, {}); }); retValue = Object.keys(count).map((cv) => count[cv]); console.debug(retValue); //working var getKeys = []; getKeys = Object.keys(retValue); //not working var getValues = []; ....
预期结果
["Team A", "Team B"] , [2 , 3]
原始JS对象
{ "jsonArray": [{ "teams": [ { "text": "Team A", "id": 1, "value": 500, "parentId": 333 }, { "text": "Team B", "id": 2, "value": 600, "parentId": 444 } ], "duty": [ { "text": "Meetings", "id": 11, "value": 100, "parentId": 500 }, { "text": "Lunch", "id": 12, "value": 101, "parentId": 500 }, { "text": "Time Cards", "id": 13, "value": 102, "parentId": 600 }, { "text": "Parking", "id": 14, "value": 103, "parentId": 600 }, { "text": "Breakfast", "id": 15, "value": 104, "parentId": 600 } ] }] };
解决方案
你的代码核心问题是retValue被处理成了包含统计对象的数组,Object.keys(retValue)取的是数组索引而非团队名称。要保证团队顺序和原始数据一致,必须基于原始teams数组的顺序提取,而非依赖统计对象的键顺序。
修改后的代码(基于你原有逻辑调整)
var retValue = []; var count = this.jsonArray.map((cv) => { var teams = cv["teams"].reduce((acc, team) => { acc[team["value"]] = team["text"]; return acc; }, {}); return cv["duty"].reduce((acc, duty) => { acc[teams[duty["parentId"]]] = acc[teams[duty["parentId"]]] ? acc[teams[duty["parentId"]]] + 1 : 1; return acc; }, {}); }); // 取数组中第一个统计对象(因为jsonArray只有一个元素) const statsObj = count[0]; // 从原始teams数组提取名称,保证顺序一致 const getKeys = this.jsonArray[0].teams.map(team => team.text); // 根据团队名称匹配对应统计值 const getValues = getKeys.map(key => statsObj[key]); console.log(getKeys); // ["Team A", "Team B"] console.log(getValues); // [2, 3]
更简洁的实现方式
// 假设已获取原始数据对象 const { jsonArray } = 你的原始数据变量; // 生成团队value到名称的映射 const teamMap = jsonArray[0].teams.reduce((map, team) => { map[team.value] = team.text; return map; }, {}); // 统计各团队任务数 const taskCount = jsonArray[0].duty.reduce((count, duty) => { const teamName = teamMap[duty.parentId]; count[teamName] = (count[teamName] || 0) + 1; return count; }, {}); // 按原始顺序提取结果 const teamNames = jsonArray[0].teams.map(t => t.text); const teamCounts = teamNames.map(name => taskCount[name]); console.log(teamNames, teamCounts); // ["Team A", "Team B"] [2, 3]
关键说明
- 不要直接用
Object.keys(statsObj)获取团队名称,虽然现代JS对象会保留键的插入顺序,但统计对象的键顺序是任务出现的顺序,和原始团队顺序可能不一致,显式基于原始teams数组提取才能确保顺序正确。 - 你的原有代码中
retValue的处理是冗余的,count本身就是包含统计对象的数组,直接取count[0]就能拿到目标统计对象。
内容的提问来源于stack exchange,提问作者Sunny
相关产品推荐
相关产品推荐

