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


606

如何计算特定字符串在另一个字符串中出现的次数。例如,这就是我要使用Javascript进行的操作:

var temp = "This is a string.";
alert(temp.count("is")); //should output '2'

19
这取决于您是否接受重叠的实例,例如var t =“ sss”; 上面的字符串中有多少个子字符串“ ss”实例?1或2?您是跳过每个实例,还是逐个字符移动指针以寻找子字符串?
蒂姆(Tim)2010年

4
此问题的答案的改进基准:jsperf.com/string-ocurrence-split-vs-match/2(基于Kazzkiq的基准)。
idmean 2015年

Answers:


1027

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

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

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

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


3
现代而优雅,但Vitimtk的解决方案效率更高。你们怎么看他的代码?
TruMan1

5
这最好地回答了这个问题。如果有人问“在特殊情况下(没有正则表达式),我该如何快10倍” Vitimtk会赢得这个问题。
Dzhaughn 2012年

121
谢谢你.. count = (str.match(/is/g) || []).length如果你没有比赛,我去了。
马特

6
我认为此答案与问题不完全匹配,因为它不像使用案例所描述的那样将字符串作为匹配的参数。当然,您可以使用RegExp构造函数并传递您要查找的字符串来动态创建regexp ,但是在这种情况下,您必须转义所有元字符。在这种情况下,纯字符串方法是更可取的。
ZER0

3
马特的答案应该在答案中!
Senči

239
/** 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;
}

用法

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

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

occurrences("foofoofoo", "foofoo"); //1

allowOverlapping

occurrences("foofoofoo", "foofoo", true); //2

火柴:

  foofoofoo
1 `----´
2    `----´

单元测试

基准测试

我进行了基准测试,我的功能比gumbo发布的regexp match函数快10倍以上。在我的测试字符串中,长度为25个字符。出现了2个字符“ o”。我在Safari中执行了1000000次。

Safari 5.1

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

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

Firefox 4

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

Benchmark>总执行时间:634毫秒(我的功能快13.5倍)


编辑:我所做的更改

  • 缓存的子串长度

  • 在字符串中添加了类型转换。

  • 添加了可选的“ allowOverlapping”参数

  • 修复了“”空子字符串大小写正确的输出。

要旨

5
我在Safari 5中重复了该测试,并使用较小的字符串(100b)获得了相似的结果,但是使用较大的字符串(16kb),regex对我来说运行得更快。对于一次迭代(不是1,000,000),相差不到一毫秒,所以我的投票投给了正则表达式。
arlomedia'4

2
+1,但您正在检查substring.length几乎每个循环,都应考虑将其缓存在while
ajax333221 2012年

1
@ ajax333221 OMG,您已经读懂了我的想法,几天前我做了这个改进,我打算编辑我​​的答案jsperf.com/count-string-occurrence-in-string
Vitim.us 2012年

4
我发现您的代码在这里使用:success-equation.com/mind_reader.html。程序员非常乐意在此放置参考。
布鲁诺·金

3
@DanielZuzevich会将类型强制转换为String,以防万一,occurrences(11,1) //2并且仍然可以使用。(这是更快,做的不是检查类型和调用这样的toString()
Vitim.us

112
function countInstances(string, word) {
   return string.split(word).length - 1;
}

4
这是一种不安全/不准确的方法,例如:countInstances("isisisisisis", "is") === 0
尼克·克拉弗

5
@Antal-看起来像以前的chrome测试版中的错误,在更新到最新版本后仍然有效,不过我仍然会避免使用此方法。
尼克·克拉弗

28
这对我来说似乎是一个完全有效的解决方案。
Gregor Schmidt 2015年

2
@NickCraver出于好奇,为什么要避开这种方法?(而不是Beta版浏览器中的错误)
Jonny Lin

6
@JonnyLin它会创建不必要的分配,当替代方案不存在时,您会立即将其丢弃-取决于数据,它们可能非常大。
尼克·克拉弗

88

您可以尝试以下方法:

var theString = "This is a string.";
console.log(theString.split("is").length - 1);


14
为简单起见,+ 1,并且根据我的测试,此解决方案的运行速度比其他解决方案快10倍
克劳迪奥·霍兰达

例如我有两个“是”,您如何获得每个的位置?
Rapidoodle

正如@Orbit的答案中所述,人们在旧版本的Chrome上获得了不同的结果。使用这种方法可能会有些谨慎。
mgthomas99 2013年

而且,您还可以将其与变量一起使用:theString.split(myvar).length - 1您无法通过简单的正则表达式来实现
Steffan

4
这是三年后@Orbit的答案 ……
aloisdg移至codidact.com,

33

我的解决方案:

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'));


5
也许最好返回(str.match(regExp)|| [])。length; 这样,您就不会对正则表达式求两次值了?
aikeru 2013年

2
您还需要countOcurrences('Hello...','.')==8
代替

19

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

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

1
如果您希望它与JS的搜索语义统一,则返回行将为return m ? m.length:-1;
科纳·奥布莱恩2014年

这比上面的其他正则表达式解决方案要好,因为如果计算出现次数的字符串是“ [”或正则表达式中具有特殊含义的任何内容,它们都会导致错误。
程序员

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


1.这只是针对单个字符的搜索,太含蓄2.即使OP询问isOCCURENCES
vladkras

1
这可能是这里最快的实现,但是如果您将“ ++ pos”替换为“ pos + =
searchFor.length



8

这是最快的功能!

为什么会更快?

  • 不按字符检查字符(1个例外)
  • 使用一会儿并增加1 var(字符计数var)与a进行循环以检查长度并增加2 vars(通常是var i和具有char计数的var)
  • 使用WAY少的var
  • 不使用正则表达式!
  • 使用(希望)高度优化的功能
  • 所有操作都尽可能地组合在一起,避免了由于多次操作而导致的速度降低

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

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

    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;
    };

由于计数器,较长的var名称和1 var的误用,因此此速度较慢。

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

    'The char "a" only shows up twice'.timesCharExist('a');

编辑:(2013/12/16)

不要与Opera 12.16或更早版本一起使用!这将比正则表达式解决方案多花将近2.5倍!

在chrome上,此解决方案将需要14ms到20ms的时间才能处理1,000,000个字符。

正则表达式解决方案花费11-14毫秒即可获得相同的数量。

使用功能(外部 String.prototype)大约需要10-13毫秒。

这是使用的代码:

    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');

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

注意:如果您希望此函数计算的字符数超过1,请更改c=(c+'')[0]c=c+''


1
原型就是一个例子!您可以随意使用该功能!您甚至可以执行以下操作:var timesFunctionExist = function(x,c){var t = 0,l = 0,c =(c +'')[0]; while(l = x.indexOf(c,l)+1 )++ t;返回t}); alert(timesCharExist('char“ a”仅显示两次','a'));! (这将加快速度,因为我不会弄乱原型)。如果您认为我错了,为什么不向我扔石头之前先展示一下呢?向我证明我的职能很糟糕,我会接受的。给我看一个测试用例。var的长度确实会影响速度。你可以测试一下。
Ismael Miguel


4

我认为regex的用途与的区别很大indexOfindexOf只需找到某个字符串的出现,而在正则表达式中就可以使用通配符,例如[A-Z],这表示它将找到任何字符串在单词中大写字符而无需说明实际字符。

例:

 var index = "This is a string".indexOf("is");
 console.log(index);
 var length = "This is a string".match(/[a-z]/g).length;
 // where [a-z] is a regex wildcard expression thats why its slower
 console.log(length);


3

超级骗子,但我今天需要做这样的事情,只想到以后再检查。对我来说工作很快。

String.prototype.count = function(substr,start,overlap) {
    overlap = overlap || false;
    start = start || 0;

    var count = 0, 
        offset = overlap ? 1 : substr.length;

    while((start = this.indexOf(substr, start) + offset) !== (offset - 1))
        ++count;
    return count;
};

3
       var myString = "This is a string.";
        var foundAtPosition = 0;
        var Count = 0;
        while (foundAtPosition != -1)
        {
            foundAtPosition = myString.indexOf("is",foundAtPosition);
            if (foundAtPosition != -1)
            {
                Count++;
                foundAtPosition++;
            }
        }
        document.write("There are " + Count + " occurrences of the word IS");

请参阅:- 计算子字符串出现在字符串中以进行逐步说明。


3

建立在@ Vittim.us上面的答案上。我喜欢他的方法提供给我的控件,使它易于扩展,但是我需要增加不区分大小写并在支持标点符号的情况下限制整个单词的匹配。(例如,“洗澡”在“洗澡”中,但不在“洗澡”中)

标点符号正则表达式来自:https : //stackoverflow.com/a/25575009/497745如何使用正则表达式从JavaScript中的字符串中剥离所有标点符号?

function keywordOccurrences(string, subString, allowOverlapping, caseInsensitive, wholeWord)
{

    string += "";
    subString += "";
    if (subString.length <= 0) return (string.length + 1); //deal with empty strings

    if(caseInsensitive)
    {            
        string = string.toLowerCase();
        subString = subString.toLowerCase();
    }

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

    while (true)
    {
        pos = string.indexOf(subString, pos);
        if (pos >= 0)
        {
            var matchPos = pos;
            pos += step; //slide forward the position pointer no matter what

            if(wholeWord) //only whole word matches are desired
            {
                if(matchPos > 0) //if the string is not at the very beginning we need to check if the previous character is whitespace
                {                        
                    if(!/[\s\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&\(\)*+,\-.\/:;<=>?@\[\]^_`{|}~]/.test(string[matchPos - 1])) //ignore punctuation
                    {
                        continue; //then this is not a match
                    }
                }

                var matchEnd = matchPos + subStringLength;
                if(matchEnd < stringLength - 1)
                {                        
                    if (!/[\s\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&\(\)*+,\-.\/:;<=>?@\[\]^_`{|}~]/.test(string[matchEnd])) //ignore punctuation
                    {
                        continue; //then this is not a match
                    }
                }
            }

            ++n;                
        } else break;
    }
    return n;
}

如果发现错误或改进,请随时修改和重构此答案。


3

对于将来会发现此线程的任何人,请注意,如果将其概括化,那么可接受的答案将不会总是返回正确的值,因为它会阻塞诸如$和的正则表达式运算符.。这是一个更好的版本,可以处理任何针:

function occurrences (haystack, needle) {
  var _needle = needle
    .replace(/\[/g, '\\[')
    .replace(/\]/g, '\\]')
  return (
    haystack.match(new RegExp('[' + _needle + ']', 'g')) || []
  ).length
}

3

function get_occurrence(varS,string){//Find All Occurrences
        c=(string.split(varS).length - 1);
        return c;
    }
    temp="This is a string.";
    console.log("Total Occurrence is "+get_occurrence("is",temp));

使用get_occurrence(varS,string)查找字符串中字符和字符串的出现。




2

没人会看到这一点,但是最好偶尔带回递归和箭头功能(双关语是光荣的)

String.prototype.occurrencesOf = function(s, i) {
 return (n => (n === -1) ? 0 : 1 + this.occurrencesOf(s, n + 1))(this.indexOf(s, (i || 0)));
};


1

现在,这是我遇到的一个非常古老的线程,但是由于许多人都提出了自己的答案,这里是我的希望,希望可以帮助使用此简单代码的人。

var search_value = "This is a dummy sentence!";
var letter = 'a'; /*Can take any letter, have put in a var if anyone wants to use this variable dynamically*/
letter = letter && "string" === typeof letter ? letter : "";
var count;
for (var i = count = 0; i < search_value.length; count += (search_value[i++] == letter));
console.log(count);

我不确定这是否是最快的解决方案,但为了简单起见并且不使用正则表达式,我更喜欢它(我只是不喜欢使用它们!)


1

此函数返回单词在文本中出现的次数。

请注意,无论单词和文本的格式(大写,大写...)如何,我们都使用toLowerCase计算出现的次数

wordCount(text, word) {
    if (!text || !word) {
      return 0;
    }
    text = text.toLowerCase();
    word = word.toLowerCase();
    return ( text.split( word ).length - 1 );
}

0

Leandro Batista的答案:正则表达式的问题。

 "use strict";
 var dataFromDB = "testal";
 
  $('input[name="tbInput"]').on("change",function(){
	var charToTest = $(this).val();
	var howManyChars = charToTest.length;
	var nrMatches = 0;
	if(howManyChars !== 0){
		charToTest = charToTest.charAt(0);
		var regexp = new RegExp(charToTest,'gi');
		var arrMatches = dataFromDB.match(regexp);
		nrMatches = arrMatches ? arrMatches.length : 0;
	}
		$('#result').html(nrMatches.toString());

  });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="main">
What do you wanna count <input type="text" name="tbInput" value=""><br />
Number of occurences = <span id="result">0</span>
</div>


0

var countInstances = function(body, target) {
  var globalcounter = 0;
  var concatstring  = '';
  for(var i=0,j=target.length;i<body.length;i++){
    concatstring = body.substring(i-1,j);
    
    if(concatstring === target){
       globalcounter += 1;
       concatstring = '';
    }
  }
  
  
  return globalcounter;
 
};

console.log(   countInstances('abcabc', 'abc')   ); // ==> 2
console.log(   countInstances('ababa', 'aba')   ); // ==> 2
console.log(   countInstances('aaabbb', 'ab')   ); // ==> 1


0

有点晚了,但是假设我们有以下字符串:

var temp = "This is a string.";

首先,我们根据您要匹配的内容进行拆分,这将返回一个字符串数组。

var array = temp.split("is");

然后,我们得到它的长度并减去1,因为split默认默认为大小为1的数组,因此每次发现事件时都会增加其大小。

var occurrenceCount = array.length - 1;
alert(occurrenceCount); //should output '2'

您还可以在一行中完成所有这些操作,如下所示:

alert("This is a string.".split("is").length - 1); //should output '2'

希望对您有帮助:D


1
我可以将其标记为重复的答案吗?也许您应该在提供自己的答案之前先阅读所有答案?
米歇尔

2
这是八年后@Orbit的答案 ……
aloisdg移至codidact.com,

1
那我应该删除此回复吗?
Juan Enrique Segebre

0

该解决方案基于.replace()将RegEx作为第一个参数并将函数作为第二个参数的方法,我们可以将其用作闭包来增加计数器...

/**
 * Return the frequency of a substring in a string
 * @param {string} string - The string.
 * @param {string} string - The substring to count.
 * @returns {number} number - The frequency.
 * 
 * @author Drozerah https://gist.github.com/Drozerah/2b8e08d28413d66c3e63d7fce80994ce
 * @see https://stackoverflow.com/a/55670859/9370788
 */
const subStringCounter = (string, subString) => {

    let count = 0
    string.replace(new RegExp(subString, 'gi'), () => count++)
    return count
}

用法

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

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

0

遇到了这个职位。

let str = 'As sly as a fox, as strong as an ox';

let target = 'as'; // let's look for it

let pos = 0;
while (true) {
  let foundPos = str.indexOf(target, pos);
  if (foundPos == -1) break;

  alert( `Found at ${foundPos}` );
  pos = foundPos + 1; // continue the search from the next position
}

可以将相同的算法布置得更短:

let str = "As sly as a fox, as strong as an ox";
let target = "as";

let pos = -1;
while ((pos = str.indexOf(target, pos + 1)) != -1) {
  alert( pos );
}

0

substr_count 从php转换为Javascript


function substr_count (haystack, needle, offset, length) { 
  // eslint-disable-line camelcase
  //  discuss at: https://locutus.io/php/substr_count/
  // original by: Kevin van Zonneveld (https://kvz.io)
  // bugfixed by: Onno Marsman (https://twitter.com/onnomarsman)
  // improved by: Brett Zamir (https://brett-zamir.me)
  // improved by: Thomas
  //   example 1: substr_count('Kevin van Zonneveld', 'e')
  //   returns 1: 3
  //   example 2: substr_count('Kevin van Zonneveld', 'K', 1)
  //   returns 2: 0
  //   example 3: substr_count('Kevin van Zonneveld', 'Z', 0, 10)
  //   returns 3: false

  var cnt = 0

  haystack += ''
  needle += ''
  if (isNaN(offset)) {
    offset = 0
  }
  if (isNaN(length)) {
    length = 0
  }
  if (needle.length === 0) {
    return false
  }
  offset--

  while ((offset = haystack.indexOf(needle, offset + 1)) !== -1) {
    if (length > 0 && (offset + needle.length) > length) {
      return false
    }
    cnt++
  }

  return cnt
}

查看Locutus对Php的substr_count函数的翻译


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.