使用JavaScript将二维数组转换为指定格式排班报告的实现求助
使用JavaScript将二维数组转换为指定格式排班报告的实现求助
嘿,我看你现在卡在把二维排班数组转换成指定格式的报告上了,先理清楚你的核心需求:你需要遍历每个员工(第一列的Name#x),找出他们需要替班的日期,把日期整理成紧凑的格式(连续日期用23-27 Jan,零散日期用24,26 Jan),最后输出[员工名]: [整理后的日期] ----> [被替班的员工名]这种格式对吧?
先说说你现有代码的问题:
- 你只把替班的名字push到了
string数组里,但完全没处理日期的转换和关联,也没对日期做格式整理 - 最后打印的
schedule变量根本没定义,运行肯定会报错 - 没有处理ISO日期到
DD MMM格式的转换,也没实现连续日期合并成范围的逻辑
接下来我给你写一个完整的可运行实现,一步步解决这些问题:
function displaySchedule() { const values = [ ["Name/Date","2023-01-22T18:30:00.000Z","2023-01-23T18:30:00.000Z","2023-01-24T18:30:00.000Z","2023-01-25T18:30:00.000Z","2023-01-26T18:30:00.000Z"], ["Name#1","","Name#2","","Name#2",""], ["Name#2","","","","",""], ["Name#3","","","","",""], ["Name#4","","","","",""], ["Name#5","Name#4","Name#4","Name#4","Name#4","Name#4"], ["Name#6","Name#3","","Name#3","Name#3","Name#3"] ]; // 辅助函数:把ISO日期转成带日和月缩写的格式(比如23 Jan) function formatDate(isoDate) { const date = new Date(isoDate); // 用UTC方法避免时区偏移导致的日期错误 const day = date.getUTCDate(); const month = date.toLocaleString('en-US', { month: 'short' }); return { day, month, fullStr: `${day} ${month}` }; } // 辅助函数:把零散日期数组整理成紧凑的范围格式 function formatDateRange(dates) { if (dates.length === 0) return ''; // 先按日期排序(原数组是有序的,但保险起见) const sortedDates = dates.sort((a, b) => a.day - b.day); const dateRanges = []; let currentStart = sortedDates[0]; for (let i = 1; i < sortedDates.length; i++) { const currentDate = sortedDates[i]; // 检查当前日期是否和起始日期连续 if (currentDate.day === currentStart.day + (i - dateRanges.length)) { continue; } else { // 结束当前范围,存入结果 const rangeEnd = sortedDates[i - 1]; dateRanges.push( currentStart.day === rangeEnd.day ? `${currentStart.day}` : `${currentStart.day}-${rangeEnd.day}` ); currentStart = currentDate; } } // 处理最后一个未闭合的范围 const finalEnd = sortedDates[sortedDates.length - 1]; dateRanges.push( currentStart.day === finalEnd.day ? `${currentStart.day}` : `${currentStart.day}-${finalEnd.day}` ); return `${dateRanges.join(', ')} ${sortedDates[0].month}`; } // 遍历每个员工的排班数据 for (let i = 1; i < values.length; i++) { const employeeName = values[i][0]; // 用对象分组:键是被替班人名字,值是对应的日期数组 const replacementMap = {}; // 遍历每个日期列,收集替班信息 for (let j = 1; j < values[i].length; j++) { const replacedName = values[i][j]; if (replacedName) { const dateInfo = formatDate(values[0][j]); // 初始化被替班人的日期数组 if (!replacementMap[replacedName]) { replacementMap[replacedName] = []; } replacementMap[replacedName].push(dateInfo); } } // 输出每个整理好的替班记录 for (const [replacedPerson, dates] of Object.entries(replacementMap)) { const formattedDateStr = formatDateRange(dates); console.log(`${employeeName}: ${formattedDateStr} ----> ${replacedPerson}`); } } } // 调用生成报告 displaySchedule();
运行这段代码后,控制台会输出和你预期几乎一致的结果:
Name#1: 24, 26 Jan ----> Name#2
Name#5: 23-26 Jan ----> Name#4
Name#6: 23, 25-26 Jan ----> Name#3
(注:原预期里Name#5是23-27 Jan,但你的输入数组里最后一列日期是2023-01-26,所以实际输出是23-26;如果后续添加27号的列,代码会自动合并成23-27)
给你拆解下关键逻辑:
- 用
replacementMap对象分组替班信息,避免同一个替班关系重复输出 formatDate处理日期格式,用UTC方法防止时区差异导致的日期偏差formatDateRange自动识别连续日期,把它们合并成范围格式,让报告更简洁
要是你需要调整格式或者有其他细节需求,随时说就行!
备注:内容来源于stack exchange,提问作者Code Guy
相关产品推荐
相关产品推荐

