如何修复Google Apps Script中不同长度数值的数组比较错误
Google Sheets Apps Script 宏数值比较Bug排查
问题概述
我写了一个用于Google Sheets的Apps Script宏,用来对比联赛各队伍的每周得分,通过不同类别分数判断胜负关系,部分类别设置了高分/低分计分逻辑。宏在多数情况下正常,但发现一个Bug:当对比的两个数值量级不同时(比如两位数vs三位数),比较结果会反转,总是给位数短的数值加1,位数相同时逻辑正常。
现有代码
// Get all relevant data from the stat sheet in one go const statsRange = statSheet.getRange('C8:C234').offset(0, weeks); const statsData = statsRange.getValues(); // Iterate through teams (assuming 12 teams) for (let i = 0; i <= 11; i++) { for (let j = 0; j <= 11; j++) { if (i===11&&j===11) {break} if (j===i) {j=j+1;} let score = 0; // Iterate through stats for each team pair, comparing and calculating score. // Scores are across 19 rows per team in the data set. There are 15 relevant rows. for (let k = 0; k <= 15; k++) { var homeStat = statsData[(19 * i) + k]; var awayStat = statsData[(19 * j) + k]; // Skip some stats and handle some differently if (k === 0 || k === 1 || k === 3 || k === 4) {continue} else if (k === 13||k === 14) { score += (homeStat < awayStat) ? 1 : (homeStat > awayStat) ? -1 : 0; } else { score += (homeStat > awayStat) ? 1 : (homeStat < awayStat) ? -1 : 0; } console.log(i, j, k, homeStat, awayStat, score) } } }
示例输入数据集
| 单元格 | 数值 |
|---|---|
| C198 | 180 |
| C199 | 409 |
| C200 | 0.44 |
| C201 | 114 |
| C202 | 148 |
| C203 | 0.77 |
| C204 | 68 |
| C205 | 542 |
| C206 | 43 |
| C207 | 174 |
| C208 | 107 |
| C209 | 28 |
| C210 | 14 |
| C211 | 55 |
| C212 | 0 |
| C213 | 0 |
| C214 | 7 |
| C215 | |
| C216 | |
| C217 | 130 |
| C218 | 273 |
| C219 | 0.476 |
| C220 | 65 |
| C221 | 82 |
| C222 | 0.793 |
| C223 | 35 |
| C224 | 360 |
| C225 | 42 |
| C226 | 142 |
| C227 | 87 |
| C228 | 31 |
| C229 | 25 |
| C230 | 52 |
| C231 | 0 |
| C232 | 1 |
| C233 | 7 |
错误日志示例
| time | log | i | j | k | home stat | away stat | score | |---------------|-------|----|----|----|-----------|-----------|-------| | 6:59:04 PM | Info | 11 | 10 | 2 | [ 0.476 ] | [ 0.44 ] | 1 | | 6:59:04 PM | Info | 11 | 10 | 5 | [ 0.793 ] | [ 0.77 ] | 2 | | 6:59:04 PM | Info | 11 | 10 | 6 | [ 35 ] | [ 68 ] | 1 | | 6:59:04 PM | Info | 11 | 10 | 7 | [ 360 ] | [ 542 ] | 0 | | 6:59:04 PM | Info | 11 | 10 | 8 | [ 42 ] | [ 43 ] | -1 | | 6:59:04 PM | Info | 11 | 10 | 9 | [ 142 ] | [ 174 ] | -2 | | 6:59:04 PM | Info | 11 | 10 | 10 | [ 87 ] | [ 107 ] | -1 | <!-- 此处错误:87 < 107,按逻辑score应减1变为-3,但实际变为-1 --> | 6:59:04 PM | Info | 11 | 10 | 11 | [ 31 ] | [ 28 ] | 0 | | 6:59:04 PM | Info | 11 | 10 | 12 | [ 25 ] | [ 14 ] | 1 | | 6:59:04 PM | Info | 11 | 10 | 13 | [ 52 ] | [ 55 ] | 2 | | 6:59:04 PM | Info | 11 | 10 | 14 | [ 0 ] | [ 0 ] | 2 | | 6:59:04 PM | Info | 11 | 10 | 15 | [ 1 ] | [ 0 ] | 3 |
问题原因
核心问题是statsData是通过getValues()获取的二维数组,每一个元素都是单元素数组(比如[87]),而非原始数值。直接用数组做大小比较时,JavaScript会将数组转换为字符串(比如[87].toString()得到"87"),然后按字符串字典序比较:
"87"和"107"比较时,第一个字符"8"的ASCII码大于"1",所以[87]会被判定为大于[107],导致计分逻辑反转。
修复方案
将获取到的数组元素转换为数值类型,同时处理空值避免出现NaN:
修改后的关键代码片段
for (let k = 0; k <= 15; k++) { // 提取数组中的数值,空值转为0或根据需求处理 const homeStat = Number(statsData[(19 * i) + k][0]) || 0; const awayStat = Number(statsData[(19 * j) + k][0]) || 0; // Skip some stats and handle some differently if (k === 0 || k === 1 || k === 3 || k === 4) {continue} else if (k === 13||k === 14) { score += (homeStat < awayStat) ? 1 : (homeStat > awayStat) ? -1 : 0; } else { score += (homeStat > awayStat) ? 1 : (homeStat < awayStat) ? -1 : 0; } console.log(i, j, k, homeStat, awayStat, score) }
说明
- 使用
Number()将数组中的值转为数值类型,[0]取数组的第一个元素(因为getValues()返回的是每行一个数组)。 - 用
|| 0处理空单元格的情况,避免转换后得到NaN,可根据实际需求调整为空值的处理逻辑(比如视为0或跳过)。
内容的提问来源于stack exchange,提问作者user3225844
相关产品推荐
相关产品推荐

