74

What is the simplest way to count the number of occurrences of a specific character in a string?

That is, I need to write a function, countTheCharacters(), so that

str = "the little red hen"
count = countTheCharacters(str,"e") ' Count should equal 4
count = countTheCharacters(str,"t") ' Count should equal 3
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Urbycoz
  • 7,247
  • 20
  • 70
  • 108
  • The fastest way is not to use a string. If you really interested in speed you should look for something else. – habakuk Feb 19 '16 at 10:13
  • 1
    @habakuk, what non-string value could the OP use instead of "the little red hen"? – johny why Mar 08 '16 at 22:10
  • @johnywhy use a StringBuilder. See https://msdn.microsoft.com/de-de/library/system.text.stringbuilder%28v=vs.110%29.aspx?cs-save-lang=1&cs-lang=vb#code-snippet-11 – habakuk Mar 09 '16 at 21:43

26 Answers26

81

The most straightforward is to simply loop through the characters in the string:

Public Function CountCharacter(ByVal value As String, ByVal ch As Char) As Integer
  Dim cnt As Integer = 0
  For Each c As Char In value
    If c = ch Then 
      cnt += 1
    End If
  Next
  Return cnt
End Function

Usage:

count = CountCharacter(str, "e"C)

Another approach that is almost as effective and gives shorter code is to use LINQ extension methods:

Public Function CountCharacter(ByVal value As String, ByVal ch As Char) As Integer
  Return value.Count(Function(c As Char) c = ch)
End Function
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Guffa
  • 687,336
  • 108
  • 737
  • 1,005
  • 1
    I came here looking for the *fastest* approach, not necessarily the most elegant one. This is quick, but can be made about 10% quicker by using `For i as Integer = 0 to value.Length - 1` instead of a For Each loop. – NightOwl888 Aug 13 '14 at 19:34
  • `'Count' is not a member of 'String'.` – Panzercrisis Oct 14 '14 at 14:57
  • 1
    @Panzercrisis: The `Count` method is an extension method to `IEnumerable`, and `String` implements `IEnumerable`. If you get a compiler error like that, you are missing the `using System.Linq;` reference at the top of the page. – Guffa Oct 14 '14 at 17:14
  • 2
    This logic can be used for VBA as well: `Public Function CountCharacter(ByVal value As String, ByVal ch As Char) As Integer Dim cnt As Integer For Each c In value If c = ch Then cnt = cnt + 1 End If Next CountCharacter = cnt End Function` – Reverend_Dude Dec 09 '14 at 16:28
  • Don't you just love conciseness! I fell in love with the last example using Linq: ```Dim myString As String = "This is a string in which I am going to count the occurrences of " Dim countChar As Char = "o" Dim count As Integer = myString.Count(Function(c As Char) c = countChar)``` – JohnRDOrazio Jan 06 '16 at 23:28
  • 2
    The code in the answer and in the comments do not paste into VBA and work on the first try. Here is some VBA code in case somebody is looking for it: Private Function CountCharacter(WhatToSearch As String, SearchForThis As String) As Long Dim NumberOfHits As Long Dim i As Long For i = 1 To Len(WhatToSearch) If Mid(WhatToSearch, i, 1) = SearchForThis Then NumberOfHits = NumberOfHits + 1 End If Next CountCharacter = NumberOfHits End Function – RedDragonWebDesign Mar 31 '16 at 11:10
72

This is the simple way:

text = "the little red hen"
count = text.Split("e").Length -1 ' Equals 4
count = text.Split("t").Length -1 ' Equals 3
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Coyolero
  • 2,353
  • 4
  • 25
  • 34
  • 2
    This gives not always the correct number if the start letter or/and endletter is the one to count – Reman Jul 23 '13 at 12:11
  • 1
    @Remonn It always gives the correct number for me. The only way it doesn't count start/end letters is if you pass `SplitStringOptions.RemoveEmptyEntries` as the second parameter to Split() – alldayremix Sep 06 '13 at 17:46
  • 1
    This is simple, but it creates a bunch of strings that are not even used for anything. – Guffa Oct 14 '14 at 19:17
  • @Guffa, since the split is not applied to a variable, won't any memory allocated to the split be released immediately, or as soon as we exit the function? Depends on specific language, i suppose.... – johny why Mar 08 '16 at 22:16
  • 2
    @johnywhy: The memory is not released immediately, the strings remain in memory until the garbage collector can collect them. Short lived objects are quite common and the garbage collector is optimised to handle them efficiently, but they still increase the allocation throughput and causes more work for the garbage collector. This is handled by the framework, so it's the same for all .NET languages. – Guffa Mar 08 '16 at 22:40
  • Thanks. The idea functions very well for VBA too! `count = ubound(Split("the little red hen","e") 'Equals 4` – Marcelo Scofano Diniz Jan 23 '20 at 02:02
36

You can try this

Dim occurCount As Integer = Len(testStr) - Len(testStr.Replace(testCharStr, ""))
Mat
  • 202,337
  • 40
  • 393
  • 406
Mark Harris
  • 361
  • 3
  • 2
  • 4
    Divide your answer by `Len(testCharStr)` and `Ceil` it to work this for occurences of strings also. – Nikhil Agrawal Feb 11 '13 at 10:17
  • nice thing about this method is, it uses very basic fx. No LINQ, RegEx, or other extra libraries. Can be easily duplicated in various languages. – johny why Mar 08 '16 at 22:13
22

Here's a simple version.

text.count(function(x) x = "a")

The above would give you the number of a's in the string. If you wanted to ignore case:

text.count(function(x) Ucase(x) = "A")

Or if you just wanted to count letters:

text.count(function(x) Char.IsLetter(x) = True)

Give it a shot!

MattB
  • 2,203
  • 5
  • 26
  • 48
  • This doesn't look like a vb.net solution to me. – Jonny Jan 25 '17 at 12:22
  • That's a very VB.NET solution! – Adam Apr 24 '17 at 10:48
  • Fails. My VS 2017 doesn't have .count for a string. – Doug Null Oct 20 '18 at 04:23
  • @DougNull I've gotten away from VB and .Net development. I might mess with this a bit when I get home. Have you tried importing Linq? I'm wondering if that would make a difference. I can assure you that this worked for me and others in the past, but you'll note that the solution was posted in 2014. I don't know if changes that broke this have occurred since then. It would be disappointing to me if they had. Might just be a change in how lambda expressions are implemented? – MattB Dec 20 '18 at 23:38
7

Thanks, @guffa. The ability to do it in one line, or even within a longer statement in .NET is very handy. This VB.NET example counts the number of LineFeed characters:

Dim j As Integer = MyString.Count(Function(c As Char) c = vbLf)

j returns the number of LineFeeds in MyString.

Community
  • 1
  • 1
Neil Dunlop
  • 387
  • 3
  • 16
5

Or (in VB.NET):

Function InstanceCount(ByVal StringToSearch As String,
                       ByVal StringToFind As String) As Long
    If Len(StringToFind) Then
        InstanceCount = UBound(Split(StringToSearch, StringToFind))
    End If
End Function
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
JerryOL
  • 1,419
  • 1
  • 20
  • 26
5

Conversion of Ujjwal Manandhar's code to VB.NET as follows...

Dim a As String = "this is test"
Dim pattern As String = "t"
Dim ex As New System.Text.RegularExpressions.Regex(pattern)
Dim m As System.Text.RegularExpressions.MatchCollection
m = ex.Matches(a)
MsgBox(m.Count.ToString())
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Nikc
  • 51
  • 1
  • 1
  • thanks, I choose this version. Seems to be very fast as well. I was actually searching for CR and/or LF in a text string, and the frequency so I could adjust the size and height of a textbox in a Gridview to support the output. – htm11h Mar 03 '15 at 20:46
3

I think this would be the easiest:

Public Function CountCharacter(ByVal value As String, ByVal ch As Char) As Integer
  Return len(value) - len(replace(value, ch, ""))
End Function
Jeremy
  • 39
  • 1
2
Public Function CountOccurrences(ByVal StToSerach As String, ByVal StToLookFor As String) As Int32

    Dim iPos = -1
    Dim iFound = 0
    Do
        iPos = StToSerach.IndexOf(StToLookFor, iPos + 1)
        If iPos <> -1 Then
            iFound += 1
        End If<br/>
    Loop Until iPos = -1
    Return iFound
End Function

Code Usage:

Dim iCountTimes As Integer = CountOccurrences("Can I call you now?", "a")

Also you can have it as an extension:

<Extension()> _
Public Function CountOccurrences(ByVal StToSerach As String, ByVal StToLookFor As String) As Int32
    Dim iPos = -1
    Dim iFound = 0
    Do
        iPos = StToSerach.IndexOf(StToLookFor, iPos + 1)
        If iPos <> -1 Then
            iFound += 1
        End If
    Loop Until iPos = -1
    Return iFound
End Function

Code Usage:

Dim iCountTimes2 As Integer = "Can I call you now?".CountOccurrences("a")
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
  • 1
    On Stack Overflow you can format code using the {} button in the editor. I've made this as an edit for you this time. – Flexo Jun 16 '12 at 11:02
2
Public Class VOWELS

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim str1, s, c As String
        Dim i, l As Integer
        str1 = TextBox1.Text
        l = Len(str1)
        c = 0
        i = 0
        Dim intloopIndex As Integer
        For intloopIndex = 1 To l
            s = Mid(str1, intloopIndex, 1)
            If (s = "A" Or s = "a" Or s = "E" Or s = "e" Or s = "I" Or s = "i" Or s = "O" Or s = "o" Or s = "U" Or s = "u") Then
                c = c + 1
            End If
        Next
        MsgBox("No of Vowels: " + c.ToString)
    End Sub
End Class
andrewsi
  • 10,807
  • 132
  • 35
  • 51
2

When I found this solution I was looking for something slightly different as the string I wanted to count was longer than one character, so I came up with this solution:

    Public Shared Function StrCounter(str As String, CountStr As String) As Integer
        Dim Ctr As Integer = 0
        Dim Ptr As Integer = 1
        While InStr(Ptr, str, CountStr) > 0
            Ptr = InStr(Ptr, str, CountStr) + Len(CountStr)
            Ctr += 1
        End While
        Return Ctr
    End Function
John Conde
  • 217,595
  • 99
  • 455
  • 496
Andrew'
  • 41
  • 5
2

I suggest you to do it like this:

String.Replace("e", "").Count
String.Replace("t", "").Count

You can also use .Split("e").Count - 1 or .Split("t").Count - 1 respectively, but it gives wrong values if you, for instance have an e or a t at the beginning of the String.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Olex White
  • 29
  • 1
  • 1
    Is this vb.net? i don't have visual studio installed, but both dotnetfiddle.net and ideone.com report "'count' is not a member of 'String'." – johny why Mar 08 '16 at 22:45
2

Using Regular Expressions...

Public Function CountCharacter(ByVal value As String, ByVal ch As Char) As Integer
  Return (New System.Text.RegularExpressions.Regex(ch)).Matches(value).Count
End Function
Carter Medlin
  • 11,857
  • 5
  • 62
  • 68
1

I use LINQ, and the solution is very simple:

Code in C#:

count = yourString.ToCharArray().Count(c => c == 'e');

The code in a function:

public static int countTheCharacters(string str, char charToCount){
   return str.ToCharArray().Count(c => c == charToCount);
}

Call the function:

count = countTheCharacters(yourString, 'e');
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Juan Carlos Velez
  • 2,840
  • 2
  • 34
  • 48
1
eCount = str.Length - Replace(str, "e", "").Length
tCount = str.Length - Replace(str, "t", "").Length
Güven Acar
  • 95
  • 1
  • 10
1

What huge codes for something so simple:

In C#, create an extension method and use LINQ.

public static int CountOccurences(this string s, char c)
{
    return s.Count(t => t == c);
}

Usage:

int count = "toto is the best".CountOccurences('t');

Result: 4.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Fred
  • 11
  • 1
1

Another possibility is to work with Split:

Dim tmp() As String
tmp = Split(Expression, Delimiter)
Dim count As Integer = tmp.Length - 1
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
SwissGuy
  • 565
  • 1
  • 6
  • 18
0

I found the best answer :P :

String.ToString.Count - String.ToString.Replace("e", "").Count
String.ToString.Count - String.ToString.Replace("t", "").Count
Olex White
  • 29
  • 1
0
    ' Trying to find the amount of "." in the text
    ' if txtName looks like "hi...hi" then intdots will = 3
    Dim test As String = txtName.Text
    Dim intdots As Integer = 0
    For i = 1 To test.Length
        Dim inta As Integer = 0 + 1
        Dim stra As String = test.Substring(inta)
        If stra = "." Then
            intdots = intdots + 1
        End If
    Next
    txttest.text = intdots
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
0

Use:

Function fNbrStrInStr(strin As Variant, strToCount As String)
    fNbrStrInStr = UBound(Split(strin, strToCount)) - LBound(Split(strin, strToCount))
End Function

I used strin as variant to handle very long text. The split can be zero-based or one-based for low end depending on user settings, and subtracting it ensures the correct count.

I did not include a test for strcount being longer than strin to keep code concise.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
0

var charCount = "string with periods...".Count(x => '.' == x);

Teepeemm
  • 4,331
  • 5
  • 35
  • 58
Timothy Gonzalez
  • 1,802
  • 21
  • 18
0

I use the following function. It is not the most memory efficient but it is very simple to understand, supports multiple compare methods, is only 4 lines, is fast, mostly works in VBA too, will find not just individual characters but any search string (I often search for VbCrLf (s)).

Only thing missing is the ability to start search from a different "Start"

    Function inStC(myInput As String, Search As String, Optional myCompareMethod As Long = CompareMethod.Text) As Long
        If InStr(1, myInput, Search, myCompareMethod) = 0 Then Return 0
        Return UBound(Split(myInput, Search,, myCompareMethod))
    End Function

One thing I like is that it is compact to use example.

str="the little red hen"
count=inStC(str,"e") 'count should equal 4
count=inStC(str,"t") 'count should equal 3

While I am here, I would like to shill my inStB function, which, instead of returning a count of a string, it will simply return a boolean if the search string is present. I need this function often and this makes my code cleaner.

Function inStB(myInput As String, Search As String, Optional Start As Long = 1, Optional myCompareMethod As Long = CompareMethod.Text) As Boolean
    If InStr(Start, myInput, Search, myCompareMethod) > 0 Then Return True
    Return False
End Function
Shodan
  • 1,065
  • 2
  • 13
  • 35
0

Another possibility is to use a regular expression:

string a = "this is test";
string pattern = "t";
System.Text.RegularExpressions.Regex ex = new System.Text.RegularExpressions.Regex(pattern);
System.Text.RegularExpressions.MatchCollection m = ex.Matches(a);
MessageBox.Show(m.Count.ToString());

Please convert this into VB.NET.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ujjwal Manandhar
  • 2,194
  • 16
  • 20
-3

Use:

Dim a
inputString = InputBox("Enter String", "Enter Value", "")

MyString = UCase(inputString)

MsgBox MyString

Dim stringLength

stringLength = Len(MyString)

Dim temp

output = ""

i = 1
Do
    temp = Mid(MyString, i, 1)

    MsgBox temp & i

    CharacterCount = len(MyString) - len(Replace(MyString, temp, ""))

    MyString = Replace(MyString, temp, "")

    output = output & temp & ": " & CharacterCount & vbNewline

Loop While MyString <> ""

MsgBox output
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
  • What is this? It doesn't even compile, not even with `Explicit Off` and `Option Strict Off`. – Peter Mortensen Apr 01 '17 at 17:32
  • Is it some other form of Basic, like [Visual Basic 6.0](http://en.wikipedia.org/wiki/Visual_Basic#Timeline) or [VBScript](http://en.wikipedia.org/wiki/VBScript)? The question is about [VB.NET](http://en.wikipedia.org/wiki/Visual_Basic_.NET). – Peter Mortensen Apr 01 '17 at 17:39
-3
Private Sub Data_KeyPress(sender As Object, e As KeyPressEventArgs) Handles Data.KeyPress
    If Not IsNumeric(e.KeyChar) And Not e.KeyChar = ChrW(Keys.Back) And Not e.KeyChar = "." Then
        e.Handled = True
    Else
        If e.KeyChar = "." And Data.Text.ToCharArray().Count(Function(c) c = ".") > 0 Then
            e.Handled = True
        End If
    End If
End Sub
-9

Here is the direct code that solves the OP's problem:

        Dim str As String = "the little red hen"

        Dim total As Int32

        Dim Target As String = "e"
        Dim Temp As Int32
        Dim Temp2 As Int32 = -1
Line50:
        Temp = str.IndexOf(Target, Temp2 + 1)
        Temp2 = Temp
        If Temp <> -1 Then

            ' Means there is a target there
            total = total + 1
            GoTo Line50
        End If

        MessageBox.Show(CStr(total))

Now, this is a handy function to solve the OP's problem:

    Public Function CountOccurrence(ByVal YourStringToCountOccurrence As String, ByVal TargetSingleCharacterToCount As String) As Int32
        Dim total As Int32

        Dim Temp As Int32
        Dim Temp2 As Int32 = -1
Line50:
        Temp = YourStringToCountOccurrence.IndexOf(TargetSingleCharacterToCount, Temp2 + 1)
        Temp2 = Temp
        If Temp <> -1 Then

            ' Means there is a target there
            total = total + 1
            GoTo Line50
        Else
            Return total
        End If
    End Function

Example of using the function:

Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    Dim str As String = "the little red hen"

    MessageBox.Show(CStr(CountOccurrence(str, "e")))
    ' It will return 4
End Sub
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Predator
  • 1,267
  • 3
  • 17
  • 43
  • 8
    -1 Sorry but not only is that _very_ verbose, [you're using `GOTO`s !](http://www.u.arizona.edu/~rubinson/copyright_violations/Go_To_Considered_Harmful.html) – Basic Apr 03 '12 at 22:30