【问题标题】:Javascript: find all occurrences of word in text documentJavascript:查找文本文档中所有出现的单词
【发布时间】:2013-09-07 20:55:28
【问题描述】:

我正在尝试编写一个 Javascript 函数来查找文本文档中所有出现的单词的索引。目前这就是我所拥有的--

//function that finds all occurrences of string 'needle' in string 'haystack'
function getMatches(haystack, needle) {
  if(needle && haystack){
    var matches=[], ind=0, l=needle.length;
    var t = haystack.toLowerCase();
    var n = needle.toLowerCase();
    while (true) {
      ind = t.indexOf(n, ind);
      if (ind == -1) break;
      matches.push(ind);
      ind += l;
  }
  return matches;
}

但是,这给了我一个问题,因为即使它是字符串的一部分,它也会匹配单词的出现。例如,如果针是“书”,干草堆是“汤姆写了一本书。这本书的名字是 Facebook for dummies”,结果是 'book'、'book's' 和 'Facebook' 的索引,当我只想“书”的索引。我怎样才能做到这一点?任何帮助表示赞赏。

【问题讨论】:

  • 我想指出正则表达式有一个“i”标志,它会导致正则表达式以不区分大小写的方式匹配您的字符串,因此不需要.toLowerCase() 调用更多。我也在下面的一些答案中看到了它

标签: javascript regex string indexof


【解决方案1】:

这是我建议的正则表达式:

/\bbook\b((?!\W(?=\w))|(?=\s))/gi

解决您的问题。尝试使用exec() 方法。我提供的正则表达式还将考虑您提供的例句中出现的诸如“小册子”之类的词:

function getMatches(needle, haystack) {
    var myRe = new RegExp("\\b" + needle + "\\b((?!\\W(?=\\w))|(?=\\s))", "gi"),
        myArray, myResult = [];
    while ((myArray = myRe.exec(haystack)) !== null) {
        myResult.push(myArray.index);
    }
    return myResult;
}

编辑

我已经编辑了正则表达式来解释像“小册子”这样的词。我还重新格式化了我的答案,使其与您的功能相似。

你可以做一些测试here

【讨论】:

  • 非常感谢纳赛尔。这看起来很不错。您知道是否有办法将其修改为不仅限于单个单词而且还包括多单词短语?例如,如果我想搜索“书名”,它应该给我所有出现的“书名”,而不是像“书名”这样的东西。
  • 啊,我在那个正则表达式中使用的逻辑是“检查单词是否后跟 1. 后跟单词字符的非单词字符或 2. 单词字符,然后不要不要归还那些”。这不适用于“书名”的情况,因为它后面跟着一个空格和一个字母。我会调查一下看看。
【解决方案2】:

试试这个:

function getMatches(searchStr, str) {
    var ind = 0, searchStrL = searchStr.length;
    var index, matches = [];

    str = str.toLowerCase();
    searchStr = searchStr.toLowerCase();

    while ((index = str.indexOf(searchStr, ind)) > -1) {
         matches.push(index);
         ind = index + searchStrL;
    }
    return matches;
}

indexOf 返回 book 第一次出现的位置。

var str = "Tom wrote a book. The book's name is Facebook for dummies";
var n = str.indexOf("book");

【讨论】:

    【解决方案3】:

    我不知道那里发生了什么,但我可以使用正则表达式提供更好的解决方案。

    function getMatches(haystack, needle) {
        var regex = new RegExp(needle.toLowerCase(), 'g'),
            result = [];
    
        haystack = haystack.toLowerCase();
    
        while ((match = regex.exec(haystack)) != null) {
            result.push(match.index);
        }
        return result;
    }
    

    用法:

    getMatches('hello hi hello hi hi hi hello hi hello john hi hi', 'hi');
    
    Result => [6, 15, 18, 21, 30, 44, 47]
    

    考虑到您的bookbooks 的问题,您只需为"book " 提供一个空格。

    或者在你可以做的功能中。

    needle = ' ' + needle + ' ';
    

    【讨论】:

    • 我不能只用空格包围它,因为这样会错过单词结束句子的情况。例如“我读了一本书”。会错过“书”
    • @user2036311 改用这个正则表达式 var regex = new RegExp("\\b"+needle.toLowerCase()+"\\b(?!')",'g');
    • 感谢新功能,但这似乎并不能解决我不想要“书”的索引而只想要“书”的索引的问题,即整个单词匹配。
    猜你喜欢
    • 2013-12-12
    • 1970-01-01
    • 2021-10-30
    • 1970-01-01
    • 2019-10-05
    • 2012-06-07
    • 2012-12-14
    • 2017-03-02
    • 1970-01-01
    相关资源
    最近更新 更多