JavaScript数组对比合并:生成表格所需结构化数据
表格数据映射处理问题
我正在为后端表格准备数据,需要将数据处理成可直接映射为表格行的结构。表格表头基于查询使用的6个月日期范围,已将其与数据对比合并构建初始对象,但还需与后端返回的另一数组对比补全行数据。
原始数据
Headers数组
const headers = [ "2022-7", "2022-8", "2022-9", "2022-10", "2022-11", "2022-12" ]
Data数组
const data = [ { "planDetails": { "goals": [ { "title": "Budget", "frequency": 4 }, { "title": "clean", "frequency": 6 } ] }, "setVisits": [ { "goals": [ { "k": "clean", "v": 2 }, { "k": "Budget", "v": 2 } ], "date": "2022-9" }, { "goals": [ { "k": "clean", "v": 2 }, { "k": "Budget", "v": 2 } ], "date": "2022-10" }, { "goals": [ { "k": "Budget", "v": 1 }, { "k": "clean", "v": 2 } ], "date": "2022-8" } ] } ]
已完成的步骤(最后一步存在问题)
const output = data.shift() console.log(output) const newHeader = headers.map(i => new Date(i).toISOString()) /* console.log(newHeader) */ const visits = output.setVisits.map(i => { return {date: new Date(i.date).toISOString(), goals: i.goals}}) /* console.log(visits) */ const result = newHeader.map(item => { const info = visits.find(detail => detail.date === item); if (info) { return { date: item, goals: info.goals } } else { return { date: item, goals: 0 } } }) result.sort((a,b) => a.date > b.date) let finalArr = [] const next = output.planDetails.goals.forEach(i => { let newObj = {} if ( result.find(a => a.goals.k === i.title)) { newObj = { goal: i.title, frequency: i.frequency, elem1: { date: a[0].date, count: a[0].goals.v }, elem2: { date: a[1].date, count: a[1].goals.v } } } else if (!result.find(a => a.goals.k === i.title)) { newObj = { goal: i.title, frequency: i.frequency, elems: { date: a[0].date, count: 0 } } } finalArr.push(newObj) }) console.log(finalArr)
最后一步实现存在问题,需要找到一种简洁的方法对比对象的两个字段完成映射,无匹配字段时填充0。
期望的最终数组格式
[ {goal: 'Budget', frequency: 4, elem1: {date: "2022-7", count: 0}, elem2: {date: "2022-8", count: 1}, elem3: {date: "2022-9", count: 2}, elem4: {date: "2022-10", count: 2}, elem5: {date: "2022-11", count: 0}, elem6: {date: "2022-12", count: 0}}, {goal: 'clean', frequency: 6, elem1: {date: "2022-7", count: 0}, elem2: {date: "2022-8", count: 2}, elem3: {date: "2022-9", count: 2}, elem4: {date: "2022-10", count: 2}, elem5: {date: "2022-11", count: 0}, elem6: {date: "2022-12", count: 0}} ]
解决方案
实现思路
- 避免日期格式转换带来的匹配问题,直接使用原始
headers中的日期字符串。 - 将
setVisits数据转换为日期-目标值的映射对象,方便快速查询任意日期下的目标完成数。 - 遍历每个计划目标,为每个表头日期生成对应的
elem字段,无数据时填充count: 0。
完整代码
const headers = [ "2022-7", "2022-8", "2022-9", "2022-10", "2022-11", "2022-12" ] const data = [ { "planDetails": { "goals": [ { "title": "Budget", "frequency": 4 }, { "title": "clean", "frequency": 6 } ] }, "setVisits": [ { "goals": [ { "k": "clean", "v": 2 }, { "k": "Budget", "v": 2 } ], "date": "2022-9" }, { "goals": [ { "k": "clean", "v": 2 }, { "k": "Budget", "v": 2 } ], "date": "2022-10" }, { "goals": [ { "k": "Budget", "v": 1 }, { "k": "clean", "v": 2 } ], "date": "2022-8" } ] } ] // 提取核心数据 const { planDetails, setVisits } = data[0]; // 构建日期到目标值的映射:{ 日期: { 目标名: 数值 } } const dateGoalMap = setVisits.reduce((map, item) => { const goalObj = item.goals.reduce((goalMap, goal) => { goalMap[goal.k] = goal.v; return goalMap; }, {}); map[item.date] = goalObj; return map; }, {}); // 生成最终数组 const finalArr = planDetails.goals.map(planGoal => { const result = { goal: planGoal.title, frequency: planGoal.frequency }; // 为每个表头日期生成对应的elem字段 headers.forEach((date, index) => { const elemKey = `elem${index + 1}`; // 查找当前日期下该目标的数值,无数据则为0 const count = dateGoalMap[date]?.[planGoal.title] || 0; result[elemKey] = { date, count }; }); return result; }); console.log(finalArr);
代码说明
dateGoalMap:将分散的setVisits数据聚合为按日期分组的对象,每个日期下存储各目标的完成数,大幅提升查询效率。- 遍历计划目标时,通过
headers逐个生成elem字段,利用可选链操作符?.安全访问目标数值,无数据时默认填充0。 - 完全贴合表头顺序生成
elem字段,确保和表格列一一对应。
内容的提问来源于stack exchange,提问作者Jowz
相关产品推荐
相关产品推荐

