优化Google Apps Script:定位跨教师授课班级(解决超时问题)
解决Google Apps Script超时问题:高效查找拆分授课的班级
看起来你在处理全校时间表时遇到了脚本执行超时的困扰——四重循环虽然逻辑直观,但效率实在太低,哪怕是30行56列的数据集,重复的比较操作也会拖慢执行速度,触发Google Apps Script的时间限制。咱们先拆解下原代码的问题,再给出更高效的实现方案。
原代码的核心问题
- 四重循环的低效性:你的代码嵌套了四层循环,时间复杂度是
O(R²×C²),30行×56列的话会产生近300万次迭代,这类重复操作很容易触发超时。而且同一个班级会被多次检测(比如班级A在单元格X和Y,代码会先比较X和Y,再反过来比较Y和X,完全是重复劳动)。 - 条件判断逻辑错误:原代码里的非空判断用了
||(或),这意味着只要其中一个条件成立就会进入判断——哪怕单元格是空字符串,data[mr][mc] != undefined也是true,所以这个条件等于没加,会做很多无效的空值比较。 - 语法笔误:第三层循环里的
cc, data[0].length应该是cc < data[0].length,虽然你说没遇到死循环,但这个笔误可能会导致循环异常(大概率是你粘贴时的输入错误)。
优化后的实现方案
我们可以用**哈希表(Map)**来记录每个班级对应的教师列(表格的列索引),只需要遍历一次所有单元格,之后检查每个班级对应的教师数量是否≥2即可。这种方法的时间复杂度是O(R×C),执行效率会提升几十倍。
修正后的代码
function splitClassLocator() { // 获取工作表数据 const sh0 = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0]; const range = sh0.getDataRange(); const data = range.getValues(); // 用Map存储班级对应的教师列集合(避免重复记录同一教师的同一班级) const classTeacherMap = new Map(); // 遍历所有授课时段行(从第3行开始,索引为2)和教师列(从第2列开始,索引为1) for (let row = 2; row < data.length; row++) { for (let col = 1; col < data[row].length; col++) { const className = data[row][col].trim(); // 去除首尾空格,避免因空格导致的误判 // 跳过空值或无效的班级名称 if (!className) continue; // 如果班级已在Map中,添加当前教师列(用Set去重,同一教师的同一班级只记录一次) if (classTeacherMap.has(className)) { const teacherCols = classTeacherMap.get(className); teacherCols.add(col); } else { // 班级首次出现,创建新的Set存储教师列 classTeacherMap.set(className, new Set([col])); } } } // 筛选出被2位及以上教师拆分授课的班级 const splitClasses = []; classTeacherMap.forEach((teacherCols, className) => { if (teacherCols.size >= 2) { splitClasses.push(className); Logger.log(`拆分授课的班级:${className},涉及教师列索引:${Array.from(teacherCols).join(', ')}`); } }); // 可以根据需求返回或处理结果 Logger.log(`共找到${splitClasses.length}个拆分授课的班级:${splitClasses.join(', ')}`); return splitClasses; }
代码说明
- 用Map+Set存储数据:Map的键是班级名称,值是Set(自动去重),存储该班级出现过的教师列索引——这样同一教师的同一班级不会被重复计数。
- 单次遍历数据集:只需要遍历一次所有单元格,把班级和对应的教师列记录下来,避免了四重循环的重复比较。
- 空值处理:用
!className跳过空字符串、null、undefined等无效值,同时用trim()去除班级名称的首尾空格,避免因格式问题导致的误判。 - 结果筛选:最后遍历Map,找出教师列数量≥2的班级,就是你要找的拆分授课班级。
这个方案不仅解决了超时问题,还能避免重复记录同一班级,结果也更清晰。你可以直接替换原代码测试,应该能快速得到结果。
内容的提问来源于stack exchange,提问作者S RICHARDS
相关产品推荐
相关产品推荐

