HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Counting occurrences of substring in string

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
substringstringcountingoccurrences

Problem

I need to know how many times a substring occurs in a given string. I figured that I might as well create an extension method:

public static int Occurences(this string str, string val)
{
    string copy = str;

    int instancesOf = 0;
    int indexOfVal;

    while ((indexOfVal = copy.IndexOf(val)) != -1)
    {
        copy = copy.Remove(indexOfVal, val.Count());
        instancesOf++;
    }

    return instancesOf;
}


I'm not sure that the assignment in the while loop is good practice. Should I change this to compute the value once outside the loop, and once in the loop, like this?

int indexOfVal = copy.IndexOf(val);

while (indexOfVal != -1)
{
    copy = copy.Remove(indexOfVal, val.Count());
    instancesOf++;
    indexOfVal = copy.IndexOf(val);
}


Any and all comments appreciated, the more the better.

Solution

Your current implementation could be more efficient. Copying the passed in string and chopping it up is probably pretty expensive (I'm not a master of .NET internals though).

val.Count()


Why not val.Length? Count() is very inefficient compared to Length.

copy = copy.Remove(indexOfVal, val.Count());


We don't need to remove part of the string, just search again starting at indexOfVal + val.Length.

Here is an example using an overload of String.IndexOf:

public static int Occurences(this string str, string val)
{  
    int occurrences = 0;
    int startingIndex = 0;

    while ((startingIndex = str.IndexOf(val, startingIndex)) >= 0) 
    {
        ++occurrences;
        ++startingIndex;
    }

    return occurrences;
}


This implementation will count overlapping occurrences (so "bbb".Occurences("bb") will return 2.

If you don't want to count overlapping occurences, you can replace ++startingIndex; with:

startingIndex += val.Length


On why an exception isn't thrown in the case of "foo".Occurrences("o"), from MSDN:


If startIndex equals the length of the string instance, the method returns -1.

Code Snippets

val.Count()
copy = copy.Remove(indexOfVal, val.Count());
public static int Occurences(this string str, string val)
{  
    int occurrences = 0;
    int startingIndex = 0;

    while ((startingIndex = str.IndexOf(val, startingIndex)) >= 0) 
    {
        ++occurrences;
        ++startingIndex;
    }

    return occurrences;
}
startingIndex += val.Length

Context

StackExchange Code Review Q#85357, answer score: 8

Revisions (0)

No revisions yet.