如何优化处理超长字符串的for循环以避免内存溢出崩溃?
超长字符串解析问题:多场地坐标提取导致页面崩溃的解决方案
问题描述
我有一个长达32000字符的字符串resourcesNotGatheredString,里面存储了5个场地的玩家触碰资源单元格的x、y坐标信息。现在需要把指定场地的坐标提取到数组中。当前的for循环处理短字符串没问题,但当指定场地编号大于1时,页面直接崩溃。试过用#分割字符串,但没法提前确定分割索引,硬编码行不通;把分割逻辑塞进循环里也没起作用,求其他解决办法。
原代码如下:
var field_index = 1; for (j=0; j<resourcesNotGatheredString.length; j++) { if (resourcesNotGatheredString[j] == '#') { field_index += 1; } if (field_index != field){ continue; } if (resourcesNotGatheredString[j] == '|' && field_index == field) { j += 1; } if (resourcesNotGatheredString[j] == 'x' && field_index == field) { x_string = "" j += 1; while (resourcesNotGatheredString[j] != 'y' && field_index == field) { x_add = resourcesNotGatheredString[j]; x_string = x_string + x_add; j += 1; } resourcesNotGatheredX.push(parseInt(x_string)); } if (resourcesNotGatheredString[j] == 'y' && field_index == field) { y_string = ""; j +=1; while (resourcesNotGatheredString[j] != '|' && field_index == field) { y_add = resourcesNotGatheredString[j]; y_string = y_string + y_add; j+=1; } resourcesNotGatheredY.push(parseInt(y_string)); } }
解决方案
核心问题分析
原循环的致命问题:
- 嵌套while循环未做字符串边界判断,处理到字符串末尾时会访问
undefined,触发死循环或错误,直接卡死页面 - 多处重复判断
field_index == field,冗余且无意义 - 手动控制
j的递增逻辑容易出错,导致字符跳过或重复处理
方案1:先分割目标场地,再用正则提取坐标(推荐)
先把目标场地的子字符串从超长串中分离出来,再用正则直接匹配坐标,逻辑简洁且性能更高:
function getFieldCoordinates(sourceStr, targetField) { // 按#分割所有场地,fields[0]对应场地1,fields[1]对应场地2,以此类推 const allFields = sourceStr.split('#'); // 校验目标场地编号合法性 if (targetField < 1 || targetField > allFields.length) { return { x: [], y: [] }; } // 取出目标场地的字符串 const targetFieldStr = allFields[targetField - 1]; const xCoords = []; const yCoords = []; // 正则匹配x数字y数字的结构,自动提取数值 const coordPattern = /x(\d+)y(\d+)/g; let matchResult; while ((matchResult = coordPattern.exec(targetFieldStr)) !== null) { xCoords.push(parseInt(matchResult[1], 10)); yCoords.push(parseInt(matchResult[2], 10)); } return { x: xCoords, y: yCoords }; } // 使用示例:替换field为你的目标场地编号 const { x: resourcesNotGatheredX, y: resourcesNotGatheredY } = getFieldCoordinates(resourcesNotGatheredString, field);
优势:
- 只处理目标场地的内容,避免遍历整个32000字符的长串
- 正则匹配无需手动控制索引,彻底避免边界错误
- 自带合法性校验,不会出现无效场地的异常
方案2:修复原循环的边界问题
如果必须保留原遍历逻辑,需补上边界判断并简化冗余代码:
const resourcesNotGatheredX = []; const resourcesNotGatheredY = []; let field_index = 1; // 用let声明j,避免全局变量污染 for (let j = 0; j < resourcesNotGatheredString.length; j++) { const currentChar = resourcesNotGatheredString[j]; // 切换场地编号 if (currentChar === '#') { field_index++; // 若已超过目标场地,直接终止循环,无需继续遍历 if (field_index > field) break; continue; } // 非目标场地,跳过当前字符 if (field_index !== field) continue; // 跳过分隔符|,无需手动j++,循环会自动递增 if (currentChar === '|') continue; // 提取x坐标 if (currentChar === 'x') { let xStr = ''; j++; // 必须加边界判断,防止访问undefined while (j < resourcesNotGatheredString.length && resourcesNotGatheredString[j] !== 'y') { xStr += resourcesNotGatheredString[j]; j++; } // 确保字符串非空再转换,避免NaN if (xStr) resourcesNotGatheredX.push(parseInt(xStr, 10)); continue; } // 提取y坐标 if (currentChar === 'y') { let yStr = ''; j++; while (j < resourcesNotGatheredString.length && resourcesNotGatheredString[j] !== '|') { yStr += resourcesNotGatheredString[j]; j++; } if (yStr) resourcesNotGatheredY.push(parseInt(yStr, 10)); continue; } }
修复要点:
- 所有while循环添加
j < resourcesNotGatheredString.length判断,杜绝越界访问 - 当场地编号超过目标值时直接break循环,减少不必要的遍历
- 移除冗余的
field_index == field判断,简化逻辑 - 用
let声明局部变量,避免全局污染 - 转换数值前校验字符串非空,避免产生NaN
内容的提问来源于stack exchange,提问作者Bayley Sapara
相关产品推荐
相关产品推荐

