如何用JavaScript的reduce或forEach实现指定数据格式转换?
嘿,我来帮你搞定这个格式转换的问题!你需要把相同日期的记录合并,把不同的作业类型(assignment)作为属性放到同一个日期对象里对吧?下面我用JavaScript原生的reduce、forEach,还有你提到的lodash方法分别实现,都是符合你期望的输出格式的:
1. 使用reduce实现(推荐方案)
reduce是处理这类分组合并场景最顺手的原生方法,它可以帮我们累积结果,避免额外的变量声明:
const data = [ { date: '2018-01-08', assignment: 'java', count: 2 }, { date: '2018-01-04', assignment: 'java', count: 3 }, { date: '2018-01-04', assignment: 'javaScript', count: 2 }, { date: '2017-12-18', assignment: 'java', count: 2 }, { date: '2017-11-24', assignment: 'java', count: 2 }, { date: '2018-01-02', assignment: 'javaScript', count: 2 } ]; const formattedData = Object.values(data.reduce((accumulator, currentItem) => { // 如果累加器里还没有当前日期的对象,就初始化一个带date属性的空对象 if (!accumulator[currentItem.date]) { accumulator[currentItem.date] = { date: currentItem.date }; } // 将当前作业类型作为属性,计数作为值赋值到对应日期对象中 accumulator[currentItem.date][currentItem.assignment] = currentItem.count; return accumulator; }, {})); console.log(formattedData);
逻辑说明:
- 我们用一个空对象作为
reduce的初始累加器,键是日期字符串,值是对应合并后的对象 - 遍历每个数据项时,先检查累加器中是否存在当前日期的对象,不存在就创建一个
- 把当前项的
assignment作为属性名,count作为属性值添加到该日期对象中 - 最后用
Object.values()把累加器中的所有值提取成数组,就是你要的最终格式
2. 使用forEach实现
如果你更喜欢更直观的遍历方式,forEach也能实现,核心逻辑和reduce一致,只是手动维护累加对象和结果数组:
const data = [/* 你的原始数据 */]; const dateMap = {}; const formattedData = []; data.forEach(item => { // 如果当前日期还没被处理过,创建新对象并加入结果数组 if (!dateMap[item.date]) { const newDateObj = { date: item.date }; dateMap[item.date] = newDateObj; formattedData.push(newDateObj); } // 给对应日期对象添加作业计数属性 dateMap[item.date][item.assignment] = item.count; }); console.log(formattedData);
逻辑说明:
dateMap用来记录每个日期对应的对象引用,避免重复创建- 遇到新日期时,创建对象并同时存入
dateMap和结果数组 - 后续同日期的项直接通过
dateMap找到对应对象,添加属性即可
3. 使用Lodash实现(结合你提到的groupBy)
如果你已经在项目中使用Lodash,可以用groupBy先按日期分组,再对每组进行合并:
const _ = require('lodash'); const data = [/* 你的原始数据 */]; const formattedData = _.chain(data) .groupBy('date') // 先按日期分组,得到以日期为键的对象 .mapValues(group => { // 对每组数据进行合并,初始化带日期的对象后,逐个添加作业属性 return group.reduce((mergedObj, item) => { mergedObj[item.assignment] = item.count; return mergedObj; }, { date: group[0].date }); }) .values() // 提取所有分组后的对象为数组 .value(); console.log(formattedData);
这样几种方式都能得到你期望的输出格式,其中reduce方案最简洁高效,推荐优先使用~
内容的提问来源于stack exchange,提问作者surya teja
相关产品推荐
相关产品推荐

