Count the number of times a substring appears in a string in JavaScript

By: Ajdin Imsirovic 15 January 2021

Have you ever tried to see how many times a letter or a word appears in a string? Or how many times a value is repeated in an array? This tutorial shows you how to figure that out in JS.

Some scattered and lined-up numbers

Here’s a string:

let str = 'Lorem ipsum dolor sit amet.'

How many times does the letter i appear in the above string? It might be easy to answer this by simply counting the i letters in the string by hand. However, as our strings get bigger, we are forced to do this programmatically. Luckily, this is very easy to do.

str.split('i').length-1

This is what we get back:

2

Indeed, there are two letters i in the given string.

Additionally, we can look for longer substrings too:

let str = "Hello World!";
str.split('Hello').length-1 // returns: 1

Alternatively, we can use the match() method. With the String.prototype.match() method, we can match a string to any RegExp. If there’s a match, we’ll get back an array:

let str = "Lorem ipsum dolor sit amet.";
str.match(/i/g); // returns: (2) ["i", "i"]

We can use this behavior of the match() method to easily get the length of the returned array, or if there are no matches, the match() method returns null. That’s why we add the || [] so that we can just return an empty array (whose length is 0).

let str = "Lorem ipsum dolor sit amet.";
(str.match(/i/g || [])).length; // returns: 2
(str.match(/x/g || [])).length; // returns: 0

The beauty of this approach is that we can search for any substring, not just a single character. For example:

let str = "Hello World!";
(str.match(/Hello/g || [])).length; // returns: 1

There’s many, many ways to solve the same task in JavaScript. The third solution for this task looks like this:

1
2
3
4
5
6
7
8
9
let count = 0;
let str = "Lorem ipsum";
let query = "m";
for(let i = 0;i < str.length; i++) {
    if( str[i] === query ) {
        count++;
    }
}
console.log(count); // returns: 2

Yet another way of doing this is by using Array.prototype.map() and then filtering the array with Array.prototype.filter():

1
2
3
4
5
6
7
8
9
10
11
12
let str = "Lorem";
let arr = str.split('');
arr.map( 
    (elem, currentPos) => {
        if(elem === 'm') { 
            return currentPos 
        } 
    }
)
/* returns:
(5) [undefined, undefined, undefined, undefined, 4]
*/

Now we can add filter(Boolean) to filter only the truthy values out of the above returned array:

[undefined, undefined, undefined, undefined, 4]
    .filter(Boolean);
/* returns:
[4]
*/

So, with filter(Boolean) we get back the filtered array, showing only the position of the filtered truthy values. The good thing about this approach is that we can add more items to our if check:

1
2
3
4
5
6
7
8
9
10
11
12
let str = "Lorem";
let arr = str.split('');
arr.map( 
    (el, currentPos) => {
            if(el === 'm' || el === 'o' || el === 'e') { 
                return currentPos 
            } 
        }
    ).filter(Boolean)
/* returns:
(3) [1, 3, 4]
*/

Now we can get the exact position of the letters in a given array by altering the line that reads return currentPos to:

return currentPos - 1

Additionally, if we just append .length after filter(Boolean), we can easily count the number of found letters in the array.



Note:
This exercise comes from Book 3 of my book series on JS, available on Leanpub.com.



Feel free to check out my work here: