Count the number of occurrences of a character in a string in Javascript

JavascriptString

Javascript Problem Overview


I need to count the number of occurrences of a character in a string.

For example, suppose my string contains:

var mainStr = "str1,str2,str3,str4";

I want to find the count of comma , character, which is 3. And the count of individual strings after the split along comma, which is 4.

I also need to validate that each of the strings i.e str1 or str2 or str3 or str4 should not exceed, say, 15 characters.

Javascript Solutions


Solution 1 - Javascript

I have updated this answer. I like the idea of using a match better, but it is slower:

console.log(("str1,str2,str3,str4".match(/,/g) || []).length); //logs 3

console.log(("str1,str2,str3,str4".match(new RegExp("str", "g")) || []).length); //logs 4

Use a regular expression literal if you know what you are searching for beforehand, if not you can use the RegExp constructor, and pass in the g flag as an argument.

match returns null with no results thus the || []

The original answer I made in 2009 is below. It creates an array unnecessarily, but using a split is faster (as of September 2014). I'm ambivalent, if I really needed the speed there would be no question that I would use a split, but I would prefer to use match.

Old answer (from 2009):

If you're looking for the commas:

(mainStr.split(",").length - 1) //3

If you're looking for the str

(mainStr.split("str").length - 1) //4

Both in @Lo's answer and in my own silly performance test split comes ahead in speed, at least in Chrome, but again creating the extra array just doesn't seem sane.

Solution 2 - Javascript

There are at least five ways. The best option, which should also be the fastest (owing to the native RegEx engine) is placed at the top.

Method 1
("this is foo bar".match(/o/g)||[]).length;
// returns 2
Method 2
"this is foo bar".split("o").length - 1;
// returns 2

Split not recommended as it is resource hungry. It allocates new instances of 'Array' for each match. Don't try it for a >100MB file via FileReader. You can observe the exact resource usage using Chrome's profiler option.

Method 3
    var stringsearch = "o"
       ,str = "this is foo bar";
    for(var count=-1,index=-2; index != -1; count++,index=str.indexOf(stringsearch,index+1) );
// returns 2
Method 4

Searching for a single character

    var stringsearch = "o"
       ,str = "this is foo bar";
    for(var i=count=0; i<str.length; count+=+(stringsearch===str[i++]));
     // returns 2
Method 5

Element mapping and filtering. This is not recommended due to its overall resource preallocation rather than using Pythonian 'generators':

    var str = "this is foo bar"
    str.split('').map( function(e,i){ if(e === 'o') return i;} )
                 .filter(Boolean)
    //>[9, 10]
    [9, 10].length
    // returns 2

Share: I made this gist, with currently 8 methods of character-counting, so we can directly pool and share our ideas - just for fun, and perhaps some interesting benchmarks :)

Solution 3 - Javascript

Add this function to sting prototype :

String.prototype.count=function(c) { 
  var result = 0, i = 0;
  for(i;i<this.length;i++)if(this[i]==c)result++;
  return result;
};

usage:

console.log("strings".count("s")); //2

Solution 4 - Javascript

Simply, use the split to find out the number of occurrences of a character in a string.

mainStr.split(',').length // gives 4 which is the number of strings after splitting using delimiter comma

mainStr.split(',').length - 1 // gives 3 which is the count of comma

Solution 5 - Javascript

A quick Google search got this (from http://www.codecodex.com/wiki/index.php?title=Count_the_number_of_occurrences_of_a_specific_character_in_a_string#JavaScript)

String.prototype.count=function(s1) { 
	return (this.length - this.replace(new RegExp(s1,"g"), '').length) / s1.length;
}

Use it like this:

test = 'one,two,three,four'
commas = test.count(',') // returns 3

Solution 6 - Javascript

Here is a similar solution, but it uses Array.prototype.reduce

function countCharacters(char, string) {
  return string.split('').reduce((acc, ch) => ch === char ? acc + 1: acc, 0)
}

As was mentioned, String.prototype.split works much faster than String.prototype.replace.

Solution 7 - Javascript

You can also rest your string and work with it like an array of elements using

const mainStr = 'str1,str2,str3,str4';
const commas = [...mainStr].filter(l => l === ',').length;

console.log(commas);

Or

const mainStr = 'str1,str2,str3,str4';
const commas = [...mainStr].reduce((a, c) => c === ',' ? ++a : a, 0);

console.log(commas);

Solution 8 - Javascript

ok, an other one with regexp - probably not fast, but short and better readable then others, in my case just '_' to count

key.replace(/[^_]/g,'').length

just remove everything that does not look like your char but it does not look nice with a string as input

Solution 9 - Javascript

If you are using lodash, the _.countBy method will do this:

_.countBy("abcda")['a'] //2

This method also work with array:

_.countBy(['ab', 'cd', 'ab'])['ab'] //2

Solution 10 - Javascript

I have found that the best approach to search for a character in a very large string (that is 1 000 000 characters long, for example) is to use the replace() method.

window.count_replace = function (str, schar) {
    return str.length - str.replace(RegExp(schar), '').length;
};

You can see yet another JSPerf suite to test this method along with other methods of finding a character in a string.

Solution 11 - Javascript

Performance of Split vs RegExp

var i = 0;

var split_start = new Date().getTime();
while (i < 30000) {
  "1234,453,123,324".split(",").length -1;
  i++;
}
var split_end = new Date().getTime();
var split_time = split_end - split_start;


i= 0;
var reg_start = new Date().getTime();
while (i < 30000) {
  ("1234,453,123,324".match(/,/g) || []).length;
  i++;
}
var reg_end = new Date().getTime();
var reg_time = reg_end - reg_start;

alert ('Split Execution time: ' + split_time + "\n" + 'RegExp Execution time: ' + reg_time + "\n");

Solution 12 - Javascript

I made a slight improvement on the accepted answer, it allows to check with case-sensitive/case-insensitive matching, and is a method attached to the string object:

String.prototype.count = function(lit, cis) {
    var m = this.toString().match(new RegExp(lit, ((cis) ? "gi" : "g")));
    return (m != null) ? m.length : 0;
}

lit is the string to search for ( such as 'ex' ), and cis is case-insensitivity, defaulted to false, it will allow for choice of case insensitive matches.


To search the string 'I love StackOverflow.com' for the lower-case letter 'o', you would use:

var amount_of_os = 'I love StackOverflow.com'.count('o');

amount_of_os would be equal to 2.


If we were to search the same string again using case-insensitive matching, you would use:

var amount_of_os = 'I love StackOverflow.com'.count('o', true);

This time, amount_of_os would be equal to 3, since the capital O from the string gets included in the search.

Solution 13 - Javascript

Easiest way i found out...

Example-

str = 'mississippi';

function find_occurences(str, char_to_count){
    return str.split(char_to_count).length - 1;
}

find_occurences(str, 'i') //outputs 4

Solution 14 - Javascript

Here is my solution. Lots of solution already posted before me. But I love to share my view here.

const mainStr = 'str1,str2,str3,str4';

const commaAndStringCounter = (str) => {
  const commas = [...str].filter(letter => letter === ',').length;
  const numOfStr = str.split(',').length;

  return `Commas: ${commas}, String: ${numOfStr}`;
}

// Run the code
console.log(commaAndStringCounter(mainStr)); // Output: Commas: 3, String: 4

Here you find my REPL

Solution 15 - Javascript

s = 'dir/dir/dir/dir/'
for(i=l=0;i<s.length;i++)
if(s[i] == '/')
l++

Solution 16 - Javascript

I was working on a small project that required a sub-string counter. Searching for the wrong phrases provided me with no results, however after writing my own implementation I have stumbled upon this question. Anyway, here is my way, it is probably slower than most here but might be helpful to someone:

function count_letters() {
var counter = 0;

for (var i = 0; i < input.length; i++) {
    var index_of_sub = input.indexOf(input_letter, i);

    if (index_of_sub > -1) {
        counter++;
        i = index_of_sub;
    }
}

http://jsfiddle.net/5ZzHt/1/

Please let me know if you find this implementation to fail or do not follow some standards! :)

UPDATE You may want to substitute:

    for (var i = 0; i < input.length; i++) {

With:

for (var i = 0, input_length = input.length; i < input_length; i++) {

Interesting read discussing the above: http://www.erichynds.com/blog/javascript-length-property-is-a-stored-value

Solution 17 - Javascript

I just did a very quick and dirty test on repl.it using Node v7.4. For a single character, the standard for loop is quickest:

Some code:

// winner!
function charCount1(s, c) {
	let count = 0;
    c = c.charAt(0); // we save some time here
	for(let i = 0; i < s.length; ++i) {
		if(c === s.charAt(i)) {
			++count;
		}
	}
	return count;
}

function charCount2(s, c) {
	return (s.match(new RegExp(c[0], 'g')) || []).length;
}

function charCount3(s, c) {
	let count = 0;
	for(ch of s) {
		if(c === ch) {
			++count;
		}
	}
	return count;
}

function perfIt() {
	const s = 'Hello, World!';
	const c = 'o';

	console.time('charCount1');
	for(let i = 0; i < 10000; i++) {
		charCount1(s, c);
	}
	console.timeEnd('charCount1');
	
	console.time('charCount2');
	for(let i = 0; i < 10000; i++) {
		charCount2(s, c);
	}
	console.timeEnd('charCount2');
	
	console.time('charCount3');
	for(let i = 0; i < 10000; i++) {
		charCount2(s, c);
	}
	console.timeEnd('charCount3');
}

Results from a few runs:

perfIt()
charCount1: 3.301ms
charCount2: 11.652ms
charCount3: 174.043ms
undefined

perfIt()
charCount1: 2.110ms
charCount2: 11.931ms
charCount3: 177.743ms
undefined

perfIt()
charCount1: 2.074ms
charCount2: 11.738ms
charCount3: 152.611ms
undefined

perfIt()
charCount1: 2.076ms
charCount2: 11.685ms
charCount3: 154.757ms
undefined

Update 2021-Feb-10: Fixed typo in repl.it demo

Update 2020-Oct-24: Still the case with Node.js 12 (play with it yourself here)

Solution 18 - Javascript

What about string.split(desiredCharecter).length-1

Example:

var str = "hellow how is life"; var len = str.split("h").length-1; will give count 2 for character "h" in the above string;

Solution 19 - Javascript

The fastest method seems to be via the index operator:

function charOccurances (str, char)
{
  for (var c = 0, i = 0, len = str.length; i < len; ++i)
  {
    if (str[i] == char)
    {
      ++c;
    }
  }
  return c;
}

console.log( charOccurances('example/path/script.js', '/') ); // 2

Or as a prototype function:

String.prototype.charOccurances = function (char)
{
  for (var c = 0, i = 0, len = this.length; i < len; ++i)
  {
    if (this[i] == char)
    {
      ++c;
    }
  }
  return c;
}

console.log( 'example/path/script.js'.charOccurances('/') ); // 2

Solution 20 - Javascript

I know I am late to the party here but I was rather baffled no one answered this with the most basic of approaches. A large portion of the answers provided by the community for this question are iteration based but all are moving over strings on a per-character basis which is not really efficient.

When dealing with a large string that contains thousands of characters walking over each character to get the occurance count can become rather extraneous not to mention a code-smell. The below solutions take advantage of slice, indexOf and the trusted traditional while loop. These approaches prevent us having to walk over each character and will greatly speed up the time it takes to count occurances. These follow similar logic to that you'd find in parsers and lexical analyzers that require string walks.

Using with Slice

In this approach we are leveraging slice and with every indexOf match we will move our way through the string and eliminate the previous searched potions. Each time we call indexOf the size of the string it searches will be smaller.

function countChar (char: string, search: string): number {
  
  let num: number = 0;
  let str: string = search;
  let pos: number = str.indexOf(char);
  
  while(pos > -1) {
    str = str.slice(pos + 1);
    pos = str.indexOf(char);
    num++;
  }

  return num;

}

// Call the function
countChar('x', 'foo x bar x baz x') // 3

Using with IndexOf from position

Similar to the first approach using slice but instead of augmenting the string we are searching it will leverage the from parameter in indexOf method.

function countChar (char: string, str: string): number {
  
  let num: number = 0;
  let pos: number = str.indexOf(char);
  
  while(pos > -1) {
    pos = str.indexOf(char, pos + 1);
    num++;
  }

  return num;

}

// Call the function
countChar('x', 'foo x bar x baz x') // 3

Personally, I go for the second approach over the first, but both are fine and performant when dealing with large strings but also smaller sized ones too.

Solution 21 - Javascript

The following uses a regular expression to test the length. testex ensures you don't have 16 or greater consecutive non-comma characters. If it passes the test, then it proceeds to split the string. counting the commas is as simple as counting the tokens minus one.

var mainStr = "str1,str2,str3,str4";
var testregex = /([^,]{16,})/g;
if (testregex.test(mainStr)) {
  alert("values must be separated by commas and each may not exceed 15 characters");
} else {
  var strs = mainStr.split(',');
  alert("mainStr contains " + strs.length + " substrings separated by commas.");
  alert("mainStr contains " + (strs.length-1) + " commas.");
}

Solution 22 - Javascript

I'm using Node.js v.6.0.0 and the fastest is the one with index (the 3rd method in Lo Sauer's answer).

The second is:

function count(s, c) {
  var n = 0;
  for (let x of s) {
    if (x == c)
      n++;
  }
  return n;
}

Solution 23 - Javascript

Here's one just as fast as the split() and the replace methods, which are a tiny bit faster than the regex method (in Chrome and Firefox both).

let num = 0;
let str = "str1,str2,str3,str4";
//Note: Pre-calculating `.length` is an optimization;
//otherwise, it recalculates it every loop iteration.
let len = str.length;
//Note: Don't use a `for (... of ...)` loop, it's slow!
for (let charIndex = 0; charIndex < len; ++charIndex) {
  if (str[charIndex] === ',') {
    ++num;
  }
}

Solution 24 - Javascript

And there is:

function character_count(string, char, ptr = 0, count = 0) {
	while (ptr = string.indexOf(char, ptr) + 1) {count ++}
	return count
}

Works with integers too!

Solution 25 - Javascript

var mainStr = "str1,str2,str3,str4";
var splitStr = mainStr.split(",").length - 1; // subtracting 1 is important!
alert(splitStr);

Splitting into an array gives us a number of elements, which will always be 1 more than the number of instances of the character. This may not be the most memory efficient, but if your input is always going to be small, this is a straight-forward and easy to understand way to do it.

If you need to parse very large strings (greater than a few hundred characters), or if this is in a core loop that processes large volumes of data, I would recommend a different strategy.

Solution 26 - Javascript

function len(text,char){

return text.innerText.split(string).length
}

console.log(len("str1,str2,str3,str4",","))

This is a very short function.

Solution 27 - Javascript

My solution:

function countOcurrences(str, value){
   var regExp = new RegExp(value, "gi");
   return str.match(regExp) ? str.match(regExp).length : 0;  
}

Solution 28 - Javascript

The fifth method in Leo Sauers answer fails, if the character is on the beginning of the string. e.g.

var needle ='A',
  haystack = 'AbcAbcAbc';

haystack.split('').map( function(e,i){ if(e === needle) return i;} )
  .filter(Boolean).length;

will give 2 instead of 3, because the filter funtion Boolean gives false for 0.

Other possible filter function:

haystack.split('').map(function (e, i) {
  if (e === needle) return i;
}).filter(function (item) {
  return !isNaN(item);
}).length;

one more answer:

function count(string){
  const count={}
  
  string.split('').forEach(char=>{
    count[char] = count[char] ? (count[char]+1) : 1;
  })
  
  return count
}

console.log(count("abfsdfsddsfdfdsfdsfdsfda"))

Solution 29 - Javascript

I know this might be an old question but I have a simple solution for low-level beginners in JavaScript.

As a beginner, I could only understand some of the solutions to this question so I used two nested FOR loops to check each character against every other character in the string, incrementing a count variable for each character found that equals that character.

I created a new blank object where each property key is a character and the value is how many times each character appeared in the string(count).

Example function:-

function countAllCharacters(str) {
  var obj = {};
  if(str.length!==0){
    for(i=0;i<str.length;i++){
      var count = 0;
      for(j=0;j<str.length;j++){
        if(str[i] === str[j]){
          count++;
        }
      }
      if(!obj.hasOwnProperty(str[i])){
        obj[str[i]] = count;
      }
    }
  }
  return obj;
}

Solution 30 - Javascript

I believe you will find the below solution to be very short, very fast, able to work with very long strings, able to support multiple character searches, error proof, and able to handle empty string searches.

function substring_count(source_str, search_str, index) {
    source_str += "", search_str += "";
    var count = -1, index_inc = Math.max(search_str.length, 1);
    index = (+index || 0) - index_inc;
    do {
        ++count;
        index = source_str.indexOf(search_str, index + index_inc);
    } while (~index);
    return count;
}

Example usage:

console.log(substring_count("Lorem ipsum dolar un sit amet.", "m "))

function substring_count(source_str, search_str, index) {
    source_str += "", search_str += "";
    var count = -1, index_inc = Math.max(search_str.length, 1);
    index = (+index || 0) - index_inc;
    do {
        ++count;
        index = source_str.indexOf(search_str, index + index_inc);
    } while (~index);
    return count;
}

The above code fixes the major performance bug in Jakub Wawszczyk's that the code keeps on looks for a match even after indexOf says there is none and his version itself is not working because he forgot to give the function input parameters.

Solution 31 - Javascript

var a = "acvbasbb";
var b= {};
for (let i=0;i<a.length;i++){
	if((a.match(new RegExp(a[i], "g"))).length > 1){
		b[a[i]]=(a.match(new RegExp(a[i], "g"))).length;
	}
}
console.log(b);

In javascript you can use above code to get occurrence of a character in a string.

Solution 32 - Javascript

My solution with ramda js:

const testString = 'somestringtotest'

const countLetters = R.compose(
  R.map(R.length),
  R.groupBy(R.identity),
  R.split('')
)

countLetters(testString)

Link to REPL.

Solution 33 - Javascript

The function takes string str as parameter and counts occurrence of each unique characters in the string. The result comes in key - value pair for each character.

var charFoundMap = {};//object defined
    for (var i = 0; i < str.length; i++) {
        
       if(!charFoundMap[ str[i] ])  {
        charFoundMap[ str[i] ]=1;
       } 
       else
       charFoundMap[ str[i] ] +=1;
       //if object does not contain this 
    }
    return charFoundMap;

} 

Solution 34 - Javascript

let str = "aabgrhaab"
let charMap = {}

for(let char of text) {
   if(charMap.hasOwnProperty(char)){
      charMap[char]++
   } else {
     charMap[char] = 1
   }
}

console.log(charMap); //{a: 4, b: 2, g: 1, r: 1, h: 1}

Solution 35 - Javascript

There is a very tricky way, but it is in reverse:

const sampleStringText = "/john/dashboard/language";

Assume the above sample, for counting the number of forward-slashs you can do like this:

console.log( sampleStringText.split('/') - 1 );

So I recommended to use a function for it (TypeScript):

const counter = (sentence: string, char: string): number => sentence.split(char) - 1;

Solution 36 - Javascript

var i = 0;

var split_start = new Date().getTime();
while (i < 30000) {
  "1234,453,123,324".split(",").length -1;
  i++;
}
var split_end = new Date().getTime();
var split_time = split_end - split_start;


i= 0;
var reg_start = new Date().getTime();
while (i < 30000) {
  ("1234,453,123,324".match(/,/g) || []).length;
  i++;
}
var reg_end = new Date().getTime();
var reg_time = reg_end - reg_start;

alert ('Split Execution time: ' + split_time + "\n" + 'RegExp Execution time: ' + reg_time + "\n");

Solution 37 - Javascript

This below is the simplest logic, which is very easy to understand

  //Demo string with repeat char 
  let str = "Coffee"
  //Splitted the str into an char array for looping
  let strArr = str.split("")
  //This below is the final object which holds the result
  let obj = {};
  //This loop will count char (You can also use traditional one for loop)
  strArr.forEach((value,index)=>{
      //If the char exists in the object it will simple increase its value
      if(obj[value] != undefined)
      {
          obj[value] = parseInt(obj[value]) + 1;
      }//else it will add the new one with initializing 1
      else{
          obj[value] =1;
      }      
  });
 
  console.log("Char with Count:",JSON.stringify(obj)); //Char with Count:{"C":1,"o":1,"f":2,"e":2}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAkashView Question on Stackoverflow
Solution 1 - JavascriptBjornView Answer on Stackoverflow
Solution 2 - JavascriptLorenz Lo SauerView Answer on Stackoverflow
Solution 3 - Javascriptuser669677View Answer on Stackoverflow
Solution 4 - JavascriptPranjal SuccessenaView Answer on Stackoverflow
Solution 5 - Javascriptuser253751View Answer on Stackoverflow
Solution 6 - JavascriptuladzimirView Answer on Stackoverflow
Solution 7 - JavascriptYosvel Quintero ArguellesView Answer on Stackoverflow
Solution 8 - JavascripthalfbitView Answer on Stackoverflow
Solution 9 - JavascriptGeng JiawenView Answer on Stackoverflow
Solution 10 - JavascriptValera RozuvanView Answer on Stackoverflow
Solution 11 - JavascriptClive PatersonView Answer on Stackoverflow
Solution 12 - JavascriptDendromaniacView Answer on Stackoverflow
Solution 13 - JavascriptAnkur ChoraywalView Answer on Stackoverflow
Solution 14 - JavascriptMd. Jamal UddinView Answer on Stackoverflow
Solution 15 - JavascriptwlfView Answer on Stackoverflow
Solution 16 - JavascriptJakub WawszczykView Answer on Stackoverflow
Solution 17 - JavascriptNuSkoolerView Answer on Stackoverflow
Solution 18 - Javascriptuser2296195View Answer on Stackoverflow
Solution 19 - Javascriptzoran404View Answer on Stackoverflow
Solution 20 - JavascriptUser_coderView Answer on Stackoverflow
Solution 21 - JavascriptJonathan FinglandView Answer on Stackoverflow
Solution 22 - JavascriptMarc K.View Answer on Stackoverflow
Solution 23 - JavascriptGerard ONeillView Answer on Stackoverflow
Solution 24 - JavascriptDamion DooleyView Answer on Stackoverflow
Solution 25 - JavascriptNaveen KumarView Answer on Stackoverflow
Solution 26 - JavascriptDerpyCoderView Answer on Stackoverflow
Solution 27 - JavascriptGereView Answer on Stackoverflow
Solution 28 - JavascriptsaltimbokkaView Answer on Stackoverflow
Solution 29 - JavascriptViscount WathikaView Answer on Stackoverflow
Solution 30 - JavascriptJack GView Answer on Stackoverflow
Solution 31 - JavascriptNitin .View Answer on Stackoverflow
Solution 32 - JavascriptMichalView Answer on Stackoverflow
Solution 33 - JavascriptPratibha SinghView Answer on Stackoverflow
Solution 34 - JavascriptPradeeptaView Answer on Stackoverflow
Solution 35 - JavascriptAmerllicAView Answer on Stackoverflow
Solution 36 - JavascriptwebdevView Answer on Stackoverflow
Solution 37 - JavascriptAshish DevadeView Answer on Stackoverflow