[javascript] How to count string occurrence in string?

How can I count the number of times a particular string occurs in another string. For example, this is what I am trying to do in Javascript:

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

This question is related to javascript regex string

The answer is


The parameters: ustring: the superset string countChar: the substring

A function to count substring occurrence in JavaScript:

_x000D_
_x000D_
function subStringCount(ustring, countChar){
  var correspCount = 0;
  var corresp = false;
  var amount = 0;
  var prevChar = null;
  
 for(var i=0; i!=ustring.length; i++){

     if(ustring.charAt(i) == countChar.charAt(0) && corresp == false){
       corresp = true;
       correspCount += 1;
       if(correspCount == countChar.length){
         amount+=1;
         corresp = false;
         correspCount = 0;
       }
       prevChar = 1;
     }
     else if(ustring.charAt(i) == countChar.charAt(prevChar) && corresp == true){
       correspCount += 1;
       if(correspCount == countChar.length){
         amount+=1;
         corresp = false;
         correspCount = 0;
         prevChar = null;
       }else{
         prevChar += 1 ;
       }
     }else{
       corresp = false;
       correspCount = 0;
     }
 } 
 return amount;
}

console.log(subStringCount('Hello World, Hello World', 'll'));
_x000D_
_x000D_
_x000D_


Iterate less the second time (just when first letter of substring matches) but still uses 2 for loops:

   function findSubstringOccurrences(str, word) {
        let occurrences = 0;
        for(let i=0; i<str.length; i++){
            if(word[0] === str[i]){ // to make it faster and iterate less
                for(let j=0; j<word.length; j++){
                    if(str[i+j] !== word[j]) break;
                    if(j === word.length - 1) occurrences++;
                }
            }
        }
        return occurrences;
    }
    
    console.log(findSubstringOccurrences("jdlfkfomgkdjfomglo", "omg"));

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

You can try this:

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


ES2020 offers a new MatchAll which might be of use in this particular context.

Here we create a new RegExp, please ensure you pass 'g' into the function.

Convert the result using Array.from and count the length, which returns 2 as per the original requestor's desired output.

_x000D_
_x000D_
let strToCheck = RegExp('is', 'g')
let matchesReg = "This is a string.".matchAll(strToCheck)
console.log(Array.from(matchesReg).length) // 2
_x000D_
_x000D_
_x000D_


_x000D_
_x000D_
String.prototype.Count = function (find) {_x000D_
    return this.split(find).length - 1;_x000D_
}_x000D_
_x000D_
console.log("This is a string.".Count("is"));
_x000D_
_x000D_
_x000D_

This will return 2.


_x000D_
_x000D_
var str = 'stackoverflow';
var arr = Array.from(str);
console.log(arr);

for (let a = 0; a <= arr.length; a++) {
  var temp = arr[a];
  var c = 0;
  for (let b = 0; b <= arr.length; b++) {
    if (temp === arr[b]) {
      c++;
    }

  }
  console.log(`the ${arr[a]} is counted for ${c}`)
}
_x000D_
_x000D_
_x000D_


No one will ever see this, but it's good to bring back recursion and arrow functions once in a while (pun gloriously intended)

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

_x000D_
_x000D_
var temp = "This is a string.";_x000D_
console.log((temp.match(new RegExp("is", "g")) || []).length);
_x000D_
_x000D_
_x000D_


Answer for Leandro Batista : just a problem with the regex expression.

_x000D_
_x000D_
 "use strict";_x000D_
 var dataFromDB = "testal";_x000D_
 _x000D_
  $('input[name="tbInput"]').on("change",function(){_x000D_
 var charToTest = $(this).val();_x000D_
 var howManyChars = charToTest.length;_x000D_
 var nrMatches = 0;_x000D_
 if(howManyChars !== 0){_x000D_
  charToTest = charToTest.charAt(0);_x000D_
  var regexp = new RegExp(charToTest,'gi');_x000D_
  var arrMatches = dataFromDB.match(regexp);_x000D_
  nrMatches = arrMatches ? arrMatches.length : 0;_x000D_
 }_x000D_
  $('#result').html(nrMatches.toString());_x000D_
_x000D_
  });
_x000D_
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>_x000D_
<div class="main">_x000D_
What do you wanna count <input type="text" name="tbInput" value=""><br />_x000D_
Number of occurences = <span id="result">0</span>_x000D_
</div>
_x000D_
_x000D_
_x000D_


Building upon @Vittim.us answer above. I like the control his method gives me, making it easy to extend, but I needed to add case insensitivity and limit matches to whole words with support for punctuation. (e.g. "bath" is in "take a bath." but not "bathing")

The punctuation regex came from: https://stackoverflow.com/a/25575009/497745 (How can I strip all punctuation from a string in JavaScript using regex?)

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

Please feel free to modify and refactor this answer if you spot bugs or improvements.


Here is the fastest function!

Why is it faster?

  • Doesn't check char by char (with 1 exception)
  • Uses a while and increments 1 var (the char count var) vs. a for loop checking the length and incrementing 2 vars (usually var i and a var with the char count)
  • Uses WAY less vars
  • Doesn't use regex!
  • Uses an (hopefully) highly optimized function
  • All operations are as combined as they can be, avoiding slowdowns due to multiple operations

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

Here is a slower and more readable version:

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

This one is slower because of the counter, long var names and misuse of 1 var.

To use it, you simply do this:

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

Edit: (2013/12/16)

DON'T use with Opera 12.16 or older! it will take almost 2.5x more than the regex solution!

On chrome, this solution will take between 14ms and 20ms for 1,000,000 characters.

The regex solution takes 11-14ms for the same amount.

Using a function (outside String.prototype) will take about 10-13ms.

Here is the code used:

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

The result of all the solutions should be 100,000!

Note: if you want this function to count more than 1 char, change where is c=(c+'')[0] into c=c+''


I think the purpose for regex is much different from indexOf. indexOf simply find the occurance of a certain string while in regex you can use wildcards like [A-Z] which means it will find any capital character in the word without stating the actual character.

Example:

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


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

Usage

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

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

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

allowOverlapping

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

Matches:

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

Unit Test

Benchmark

I've made a benchmark test and my function is more then 10 times faster then the regexp match function posted by gumbo. In my test string is 25 chars length. with 2 occurences of the character 'o'. I executed 1 000 000 times in Safari.

Safari 5.1

Benchmark> Total time execution: 5617 ms (regexp)

Benchmark> Total time execution: 881 ms (my function 6.4x faster)

Firefox 4

Benchmark> Total time execution: 8547 ms (Rexexp)

Benchmark> Total time execution: 634 ms (my function 13.5x faster)


Edit: changes I've made

  • cached substring length

  • added type-casting to string.

  • added optional 'allowOverlapping' parameter

  • fixed correct output for "" empty substring case.

Gist


substr_count translated to Javascript from php


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
}

Check out Locutus's Translation Of Php's substr_count function


For anyone that finds this thread in the future, note that the accepted answer will not always return the correct value if you generalize it, since it will choke on regex operators like $ and .. Here's a better version, that can handle any needle:

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

You could try this

let count = s.length - s.replace(/is/g, "").length;

Super duper old, but I needed to do something like this today and only thought to check SO afterwards. Works pretty fast for me.

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

The non-regex version:

_x000D_
_x000D_
 var string = 'This is a string',_x000D_
    searchFor = 'is',_x000D_
    count = 0,_x000D_
    pos = string.indexOf(searchFor);_x000D_
_x000D_
while (pos > -1) {_x000D_
    ++count;_x000D_
    pos = string.indexOf(searchFor, ++pos);_x000D_
}_x000D_
_x000D_
console.log(count);   // 2
_x000D_
_x000D_
_x000D_


Now this is a very old thread i've come across but as many have pushed their answer's, here is mine in a hope to help someone with this simple code.

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

I'm not sure if it is the fastest solution but i preferred it for simplicity and for not using regex (i just don't like using them!)


_x000D_
_x000D_
var countInstances = function(body, target) {_x000D_
  var globalcounter = 0;_x000D_
  var concatstring  = '';_x000D_
  for(var i=0,j=target.length;i<body.length;i++){_x000D_
    concatstring = body.substring(i-1,j);_x000D_
    _x000D_
    if(concatstring === target){_x000D_
       globalcounter += 1;_x000D_
       concatstring = '';_x000D_
    }_x000D_
  }_x000D_
  _x000D_
  _x000D_
  return globalcounter;_x000D_
 _x000D_
};_x000D_
_x000D_
console.log(   countInstances('abcabc', 'abc')   ); // ==> 2_x000D_
console.log(   countInstances('ababa', 'aba')   ); // ==> 2_x000D_
console.log(   countInstances('aaabbb', 'ab')   ); // ==> 1
_x000D_
_x000D_
_x000D_


Try this:

function countString(str, search){
    var count=0;
    var index=str.indexOf(search);
    while(index!=-1){
        count++;
        index=str.indexOf(search,index+1);
    }
    return count;
}

My solution:

_x000D_
_x000D_
var temp = "This is a string.";_x000D_
_x000D_
function countOcurrences(str, value) {_x000D_
  var regExp = new RegExp(value, "gi");_x000D_
  return (str.match(regExp) || []).length;_x000D_
}_x000D_
_x000D_
console.log(countOcurrences(temp, 'is'));
_x000D_
_x000D_
_x000D_


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

Refer :- count a substring appears in the string for step by step explanation.


Just code-golfing Rebecca Chernoff's solution :-)

alert(("This is a string.".match(/is/g) || []).length);

came across this post.

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
}

The same algorithm can be layed out shorter:

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

Try it

<?php 
$str = "33,33,56,89,56,56";
echo substr_count($str, '56');
?>

<script type="text/javascript">
var temp = "33,33,56,89,56,56";
var count = temp.match(/56/g);  
alert(count.length);
</script>

Simple version without regex:

_x000D_
_x000D_
var temp = "This is a string.";_x000D_
_x000D_
var count = (temp.split('is').length - 1);_x000D_
_x000D_
alert(count);
_x000D_
_x000D_
_x000D_


You can use match to define such function:

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

 function substrCount( str, x ) {
   let count = -1, pos = 0;
   do {
     pos = str.indexOf( x, pos ) + 1;
     count++;
   } while( pos > 0 );
   return count;
 }

Examples related to javascript

need to add a class to an element How to make a variable accessible outside a function? Hide Signs that Meteor.js was Used How to create a showdown.js markdown extension Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Summing radio input values How to execute an action before close metro app WinJS javascript, for loop defines a dynamic variable name Getting all files in directory with ajax

Examples related to regex

Why my regexp for hyphenated words doesn't work? grep's at sign caught as whitespace Preg_match backtrack error regex match any single character (one character only) re.sub erroring with "Expected string or bytes-like object" Only numbers. Input number in React Visual Studio Code Search and Replace with Regular Expressions Strip / trim all strings of a dataframe return string with first match Regex How to capture multiple repeated groups?

Examples related to string

How to split a string in two and store it in a field String method cannot be found in a main class method Kotlin - How to correctly concatenate a String Replacing a character from a certain index Remove quotes from String in Python Detect whether a Python string is a number or a letter How does String substring work in Swift How does String.Index work in Swift swift 3.0 Data to String? How to parse JSON string in Typescript