JavaScript indexOf 与数百万个匹配项

javascript indexOf with millions of matches

本文关键字:百万个 数百万 indexOf JavaScript      更新时间:2023-09-26

我正在尝试从文件中提取几行表示某些XML元素。用户使用简单的 <input type="file"> 标记提供文件,并且该文件被读取为带有 FileReader 的文本,并作为此函数的参数给出:

var relevantDelimiters = [{"begin":"<header>","end":"</header>"}
,{"begin":" <someElement>","end":"</someElement>"}];
function dealWithString(invalidXML) {
  var validXML = "";
  for (var i=0; i<relevantDelimiters.length; i++) {
    delimiter = relevantDelimiters[i];
    while (invalidXML.indexOf(delimiter.begin) != -1) {
      //while there are relevant elements of this kind left: 
      startPos = invalidXML.indexOf(delimiter.begin);
      endPos = invalidXML.indexOf(delimiter.end); 
      //append to end result:
      validXML+=invalidXML.substring(startPos,endPos+delimiter.end.length)+"'n";
      //take this item out of the input to process next item
      invalidXML = invalidXML.replace(invalidXML.substring(startPos,endPos+delimiter.end.length),"");
    }
  }
  //return fixed data
  return validXML;
}

这种方法似乎适用于输入文本文件中的少量匹配项,但给定 1.5MB 的文件,脚本卡住(使用 Google Chrome 运行,使其选项卡无响应)。该文件包含大约一百万个"相关元素",这意味着来自relevantDelimiters的匹配项。

如何优化?

与其通过调用 replace 来重复"将项目从输入中取出",不如使用第二个参数来indexOffromIndex 。这样,它将搜索给定索引之后的下一个匹配项,并且您可以遍历非常大的输入而无需触摸它。

function dealWithString(invalidXML) {
  var validXML = "";
  for (var i=0; i<relevantDelimiters.length; i++) {
    var delimiter = relevantDelimiters[i],
        pos = 0,
        startPos;
    while ((startPos = invalidXML.indexOf(delimiter.begin, pos)) != -1) {
      //while there are relevant elements of this kind left:
      var endPos = invalidXML.indexOf(delimiter.end, startPos);
      // assert(endPos != -1) - otherwise this could go horribly wrong
      pos = endPos+delimiter.end.length;
      //append to end result:
      validXML += invalidXML.slice(startPos, pos) + "'n";
    }
  }
  return validXML;
}
时间花

在哪里?我假设你可以把这个大的同步动作分解成几个异步的希望。(每隔一段时间迭代,您可以在恢复之前存储索引和设置超时。这样,您就不会锁定 UI 线程。