打字稿:替换每个出现的循环。字符串操作循环

时间:2018-01-25 22:37:16

标签: javascript string loops typescript

我有一段代码,其目标是用锚标记替换@something的每一个出现。替换本身工作正常,循环通常不会。只需要考虑这是一个字符串操作方法,它必须找到某些东西,然后用其他东西替换它 - 但不能替换所有,因为它取决于'@'字符后面的内容。

这是代码。

private generateAnchors(content: string) {
    let cutIndex = 0;
    let contentToReturn = content;
    let leftToAnalyze = content;
    if (leftToAnalyze.indexOf('@') !== -1) {
        while (true) {
            leftToAnalyze = content.substring(cutIndex);
            leftToAnalyze = leftToAnalyze.substring(content.indexOf('@'));
            let tag = leftToAnalyze.substring(leftToAnalyze.indexOf('@'), leftToAnalyze.indexOf(' ', leftToAnalyze.indexOf('@')));
            cutIndex += leftToAnalyze.indexOf(tag)+tag.length;
            let address = tag.substring(1, tag.length);
            let anchor = '<a href="/home/user/'+address+'">'+tag+'</a>';
            let newContentSubString = leftToAnalyze.replace(tag, anchor);
            contentToReturn = contentToReturn.replace(leftToAnalyze, newContentSubString);
            if (leftToAnalyze.indexOf('@') === -1) break;
        }
    }
    return contentToReturn;
}

在一个小字符串中,如'hello @JEDS&amp; @Mill还@theHulk值得一提' 它工作正常。但是我发现有一个更大的字符串出现,其中@标签位于字符串的末尾,它看起来像是永远循环,并且替换它也不应该是它。

我在这段代码中监督什么?

1 个答案:

答案 0 :(得分:1)

您的cutIndex计算中存在错误。它在tag中查找leftToAnalyze的索引,并在循环开始时将该索引用于content(即leftToAnalyze = content.substring(cutIndex)),使其分析相同的文本从上一次运行开始。

cutIndex实际上应该在查看content

// cutIndex += leftToAnalyze.indexOf(tag)+tag.length;  // DON'T DO THIS
cutIndex += content.indexOf(tag)+tag.length;

此外,如果leftToAnalyze为空,循环应该提前保释:

while (true) {
  leftToAnalyze = content.substring(cutIndex);
  const indexOfFirstAt = content.indexOf('@');
  leftToAnalyze = leftToAnalyze.substring(indexOfFirstAt);

  // nothing left? bail
  if (!leftToAnalyze) break;
  ...
}

function generateAnchors(content) {
  let cutIndex = 0;
  let contentToReturn = content;
  let leftToAnalyze = content;
  if (leftToAnalyze.indexOf('@') !== -1) {
      let limit = 100;
      let i = 0;
      while (i++ < limit) {
          leftToAnalyze = content.substring(cutIndex);
          const indexOfFirstAt = content.indexOf('@');
          leftToAnalyze = leftToAnalyze.substring(indexOfFirstAt);
          if (!leftToAnalyze) break;
          const indexOfNextAt = leftToAnalyze.indexOf('@');
          const indexOfSpace = leftToAnalyze.indexOf(' ', indexOfNextAt);
          let tag = leftToAnalyze.substring(leftToAnalyze.indexOf('@'), indexOfSpace);
          cutIndex += content.indexOf(tag)+tag.length;
          let address = tag.substring(1, tag.length);
          let anchor = '<a href="/home/user/'+address+'">'+tag+'</a>';
          let newContentSubString = leftToAnalyze.replace(tag, anchor);
          contentToReturn = contentToReturn.replace(leftToAnalyze, newContentSubString);
          if (leftToAnalyze.indexOf('@') === -1) break;
      }
  }
  return contentToReturn;
}

const input = 'foo @bar baz @qux @ @@@@@';

const output = generateAnchors(input);
console.log(output);

但我建议使用正则表达式简化代码。实际上,这个循环可以简化为一行String#replace

return content.replace(/(@([^ @]+))/ig, '<a href="/home/user/$2">$1</a>');

function generateAnchors(content) {
  return content.replace(/(@([^ @]+))/ig, '<a href="/home/user/$2">$1</a>');
}

const input = 'foo @bar baz @qux @ @@@@@';

const output = generateAnchors(input);
console.log(output);

Explanation of /(@([^ @]+))/ig