How would you go about counting the number of times a string (really a char) appears in a string?

Problem

I’m working on something where I realized I needed to count how many /s I could find in a string and realized there were multiple ways to accomplish it, but I couldn’t decide which was the best (or easiest).

At the moment, I’m thinking of something along the lines of:

``````string source = "/once/upon/a/time/";
int count = source.Length - source.Replace("/", "").Length;
``````

But it doesn’t appeal to me at all; are there any takers?

I don’t think I want to look up RegEx for this.

I’m confident that my string will contain the term I’m looking for, so you can presume…

Of course, for strings with a length greater than one,

``````string haystack = "/once/upon/a/time";
string needle = "/";
int needleCount = ( haystack.Length - haystack.Replace(needle,"").Length ) / needle.Length;
``````

Solution #1

If you’re using.NET 3.5, you can achieve it with LINQ in a single line:

``````int count = source.Count(f => f == '/');
``````

If you don’t want to use LINQ, you can use the following instead:

``````int count = source.Split('/').Length - 1;
``````

You might be surprised to hear that your original method appears to be roughly 30% faster than either of them! I just ran a quick benchmark with “/once/upon/a/time/” and got the following results:

(The timeframes are for 50,000,000 iterations, so there won’t be much of a difference in real life.)

Solution #2

``````string source = "/once/upon/a/time/";
int count = 0;
foreach (char c in source)
if (c == '/') count++;
``````

It must be quicker than the source. Replace() is called by itself.

Solution #3

``````int count = new Regex(Regex.Escape(needle)).Matches(haystack).Count;
``````

Answered by Yet Another Code Maker

Solution #4

If you wish to search for entire strings rather than simply characters, use the following syntax:

``````src.Select((c, i) => src.Substring(i))
.Count(sub => sub.StartsWith(target))
``````

Read as “take the rest of the string starting from that character as a substring; count it if it starts with the target string for each character in the string.”

Solution #5

I did some investigation and discovered that Richard Watson’s technique is the fastest in the vast majority of circumstances. That’s the table with results of every solution in the post (except those use Regex because it throws exceptions while parsing string like “test{test”)

``````    Name      | Short/char |  Long/char | Short/short| Long/short |  Long/long |
Inspite   |         134|        1853|          95|        1146|         671|
LukeH_1   |         346|        4490|         N/A|         N/A|         N/A|
LukeH_2   |         152|        1569|         197|        2425|        2171|
Bobwienholt   |         230|        3269|         N/A|         N/A|         N/A|
Richard Watson|          33|         298|         146|         737|         543|
StefanosKargas|         N/A|         N/A|         681|       11884|       12486|
``````

As can be shown, the original technique is preferable for determining the number of occurrences of short substrings (1-5 characters) in a short string (10-50 characters).

You should also use the following code (based on Richard Watson’s solution) for multicharacter substrings.

``````int count = 0, n = 0;

if(substring != "")
{
while ((n = source.IndexOf(substring, n, StringComparison.InvariantCulture)) != -1)
{
n += substring.Length;
++count;
}
}
``````