如何计算字符串中的字符串出现?

Tru*_*an1 554 javascript regex string

如何计算特定字符串在另一个字符串中出现的次数.例如,这是我在Javascript中尝试做的事情:

var temp = "This is a string.";
alert(temp.count("is")); //should output '2'
Run Code Online (Sandbox Code Playgroud)

Reb*_*off 949

g正则表达式(简称全球)说,搜索整个字符串,而不是只要找到第一次出现.这匹配is两次:

var temp = "This is a string.";
var count = (temp.match(/is/g) || []).length;
console.log(count);
Run Code Online (Sandbox Code Playgroud)

并且,如果没有匹配,则返回0:

var temp = "Hello World!";
var count = (temp.match(/is/g) || []).length;
console.log(count);
Run Code Online (Sandbox Code Playgroud)

  • 谢谢你..如果你没有匹配,我去了`count =(str.match(/ is/g)|| []).length`来处理. (119认同)
  • 这最能回答这个问题.如果有人问"我怎样才能在特殊情况下(没有正则表达式)快10倍",Vitimtk将赢得这个问题. (5认同)
  • 我认为这个答案不能正确匹配问题,因为它不会像字符串一样将参数匹配,就像用例所描述的那样.当然,你可以使用`RegExp`构造函数动态创建regexp并传递你正在寻找的字符串,但在这种情况下你必须转义所有的元字符.在那种情况下,最好使用纯字符串方法. (5认同)
  • 现代而优雅,但Vitimtk的解决方案效率更高.你们对他的代码有什么看法? (3认同)
  • 马特的答案应该在答案中! (3认同)
  • 将Regex保存为繁重的代码,这是一个简单的命令-`alert(temp.split(“ is”)。length-1);` (2认同)

Vit*_*.us 228

/** Function that count occurrences of a substring in a string;
 * @param {String} string               The string
 * @param {String} subString            The sub string to search for
 * @param {Boolean} [allowOverlapping]  Optional. (Default:false)
 *
 * @author Vitim.us https://gist.github.com/victornpb/7736865
 * @see Unit Test https://jsfiddle.net/Victornpb/5axuh96u/
 * @see http://stackoverflow.com/questions/4009756/how-to-count-string-occurrence-in-string/7924240#7924240
 */
function occurrences(string, subString, allowOverlapping) {

    string += "";
    subString += "";
    if (subString.length <= 0) return (string.length + 1);

    var n = 0,
        pos = 0,
        step = allowOverlapping ? 1 : subString.length;

    while (true) {
        pos = string.indexOf(subString, pos);
        if (pos >= 0) {
            ++n;
            pos += step;
        } else break;
    }
    return n;
}
Run Code Online (Sandbox Code Playgroud)

用法

occurrences("foofoofoo", "bar"); //0

occurrences("foofoofoo", "foo"); //3

occurrences("foofoofoo", "foofoo"); //1
Run Code Online (Sandbox Code Playgroud)

allowOverlapping

occurrences("foofoofoo", "foofoo", true); //2
Run Code Online (Sandbox Code Playgroud)

火柴:

  foofoofoo
1 `----´
2    `----´
Run Code Online (Sandbox Code Playgroud)

单元测试

基准

我做了一个基准测试,我的功能比gumbo发布的正则表达式匹配功能快10倍.在我的测试字符串中是25个字符长度.2个出现的字符'o'.我在Safari中执行了1 000 000次.

Safari 5.1

基准测试>总执行时间:5617毫秒(正则表达式)

基准测试>总执行时间:881 ms(我的功能快6.4倍)

Firefox 4

基准测试>总执行时间:8547 ms(Rexexp)

基准测试>总执行时间:634毫秒(我的功能快13.5倍)


编辑:我所做的改变

  • 缓存的子串长度

  • 向字符串添加了类型转换.

  • 添加了可选的'allowOverlapping'参数

  • 修复了""空子串案例的正确输出.

要旨

  • +1带来while循环回来!(而且速度很快) (14认同)
  • 我在这里找到了您的代码:http://www.success-equation.com/mind_reader.html.非常好的程序员介意在那里提供参考. (4认同)
  • 我在Safari 5中重复了这个测试,得到了类似的结果,一个小的(100b)字符串,但是有一个更大的字符串(16kb),正则表达式对我运行得更快.对于一次迭代(不是1,000,000),差异不到一毫秒,所以我的投票去了正则表达式. (3认同)
  • @DanielZuzevich它会将类型强制转换为*String*,以防你执行`occurrence(11,1)// 2`它仍然可以工作.(以这种方式更快,而不是检查类型并调用*toString()*) (3认同)
  • +1,但你几乎在每个循环上检查`substring.length`,你应该考虑在`while`之外缓存它 (2认同)

Orb*_*bit 100

function countInstances(string, word) {
   return string.split(word).length - 1;
}
Run Code Online (Sandbox Code Playgroud)

  • 这看起来对我来说是一个非常有效的解决方案 (25认同)
  • @Antal - 看起来像之前测试版的chrome中的一个bug,在更新到最新版本后工作,但我仍然避开这个方法. (5认同)
  • @JonnyLin它会创建不必要的分配,当备选方案没有时,你会立即抛弃 - 根据数据的不同,可能会非常大. (5认同)
  • 这是一种不安全/不准确的方法,例如:`countInstances("isisisisisis","is")=== 0`. (4认同)
  • @NickCraver 出于好奇,你为什么要避开这种方法?(除了测试版浏览器中的错误) (2认同)
  • @Ast 没有 -1 计数将是错误的 (2认同)

Fre*_*Ize 82

你可以试试这个:

var theString = "This is a string.";
console.log(theString.split("is").length - 1);
Run Code Online (Sandbox Code Playgroud)

  • 为了简单而+1,因为[相应于我的测试](http://jsperf.com/string-ocurrence-split-vs-match)这个解决方案**运行速度比其他**快~10倍! (9认同)
  • 这是@Orbit 的 [答案](/sf/answers/280684001/) 三年后... (7认同)

Ger*_*ere 32

我的解决方案

var temp = "This is a string.";

function countOcurrences(str, value) {
  var regExp = new RegExp(value, "gi");
  return (str.match(regExp) || []).length;
}

console.log(countOcurrences(temp, 'is'));
Run Code Online (Sandbox Code Playgroud)

  • 也许返回会更好(str.match(regExp)|| []).那样你不会两次评估正则表达式? (5认同)
  • 你还需要scape你的字符串或`countOcurrences('你好'','.')== 8`而不是3 (2认同)

Gum*_*mbo 18

您可以match用来定义这样的功能:

String.prototype.count = function(search) {
    var m = this.match(new RegExp(search.toString().replace(/(?=[.\\+*?[^\]$(){}\|])/g, "\\"), "g"));
    return m ? m.length:0;
}
Run Code Online (Sandbox Code Playgroud)


Far*_*ini 11

非正则表达式版本:

 var string = 'This is a string',
    searchFor = 'is',
    count = 0,
    pos = string.indexOf(searchFor);

while (pos > -1) {
    ++count;
    pos = string.indexOf(searchFor, ++pos);
}

console.log(count);   // 2
Run Code Online (Sandbox Code Playgroud)

  • 这可能是这里最快的实现,但如果你用“pos+=searchFor.length”替换“++pos”会更快 (2认同)

TMS*_*TMS 10

只是代码高尔夫Rebecca Chernoff解决方案 :-)

alert(("This is a string.".match(/is/g) || []).length);
Run Code Online (Sandbox Code Playgroud)


Ism*_*uel 8

这是最快的功能!

为什么它更快?

  • 不通过char检查char(有1个例外)
  • 使用一段时间并增加1 var(char计数var)和for循环检查长度并增加2个变量(通常是var i和带有char计数的var)
  • 使用WAY减去vars
  • 不使用正则表达式!
  • 使用(希望)高度优化的功能
  • 所有操作都尽可能合并,避免因多次操作而导致的速度减慢

    String.prototype.timesCharExist=function(c){var t=0,l=0,c=(c+'')[0];while(l=this.indexOf(c,l)+1)++t;return t};
    
    Run Code Online (Sandbox Code Playgroud)

这是一个更慢,更易读的版本:

    String.prototype.timesCharExist = function ( chr ) {
        var total = 0, last_location = 0, single_char = ( chr + '' )[0];
        while( last_location = this.indexOf( single_char, last_location ) + 1 )
        {
            total = total + 1;
        }
        return total;
    };
Run Code Online (Sandbox Code Playgroud)

由于计数器,长var名称和1 var的误用,这个更慢.

要使用它,您只需执行以下操作:

    'The char "a" only shows up twice'.timesCharExist('a');
Run Code Online (Sandbox Code Playgroud)

编辑:(2013/12/16)

请勿使用Opera 12.16或更早版本!它将比正则表达式解决方案多出近2.5倍!

在chrome上,这个解决方案需要花费14到20毫秒的1,000,000个字符.

正则表达式解决方案需要11-14ms相同的数量.

使用函数(外部String.prototype)大约需要10-13ms.

这是使用的代码:

    String.prototype.timesCharExist=function(c){var t=0,l=0,c=(c+'')[0];while(l=this.indexOf(c,l)+1)++t;return t};

    var x=Array(100001).join('1234567890');

    console.time('proto');x.timesCharExist('1');console.timeEnd('proto');

    console.time('regex');x.match(/1/g).length;console.timeEnd('regex');

    var timesCharExist=function(x,c){var t=0,l=0,c=(c+'')[0];while(l=x.indexOf(c,l)+1)++t;return t;};

    console.time('func');timesCharExist(x,'1');console.timeEnd('func');
Run Code Online (Sandbox Code Playgroud)

所有解决方案的结果应该是100,000!

注意:如果你想这个函数来计算超过10个字符,改变那里是c=(c+'')[0]c=c+''


小智 8

String.prototype.Count = function (find) {
    return this.split(find).length - 1;
}

console.log("This is a string.".Count("is"));
Run Code Online (Sandbox Code Playgroud)

这将返回2。

  • 这是六年后@Orbit的[answer](/sf/answers/280684001/)... (2认同)

Sun*_*arg 7

var temp = "This is a string.";
console.log((temp.match(new RegExp("is", "g")) || []).length);
Run Code Online (Sandbox Code Playgroud)


H S*_*ogr 5

一种简单的方法是根据所需的单词(我们要计算其出现次数的单词)拆分字符串,然后从部分数量中减去 1:

function checkOccurences(string, word) {
      return string.split(word).length - 1;
}
const text="Let us see. see above, see below, see forward, see backward, see left, see right until we will be right"; 
const count=countOccurences(text,"see "); // 2
Run Code Online (Sandbox Code Playgroud)