Count all occurrences of a character in a string

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • Bassem
    Contributor
    • Dec 2008
    • 344

    Count all occurrences of a character in a string

    Hello,

    Very easy task, I know :)

    Searching the internet for a simple .NET method to do that for me brought to me this page inside Bytes.com: Count all occurrences of a character in a string

    I think they have come with working solutions, but why writing a method or a loop to do this simple task.

    It came to my mind that removing the character from the string will decrease the string Length with the character occurrence. Good but .NET does not have that Remove(char) Method, alright we can use Replace(char, char) or Replace(string, string). Lets do that.

    Lets say we have a string called search and a char called c.
    Code:
    int occurrence = search.Length - 
             search.Replace(c.ToString(), string.Empty).Length;
    Subscribing the string after the characters are removed (or replaced with nothing) from the original string will result the occurrence. Very simple, one line.


    I hope it will work for someone!


    Regards,
    Bassem
    Last edited by Bassem; May 17 '10, 02:36 PM. Reason: changed to "why writing" from "how write" based on tlhintoq's correction!
  • tlhintoq
    Recognized Expert Specialist
    • Mar 2008
    • 3532

    #2
    Why would you replace anything in a string just to count the occurances of a character?

    What problem is this "insight" supposed to solve? Counting the characters in a string is about 5 lines of code.

    This also only works if you are looking for a single character. What if you are looking for a 3 character combo?

    How often are you really looking for just 1 character in a string? May I suggest something a bit more universal? This will let you search for 1 or more characters out of a string, and return the positions of all the matches.

    Code:
            private void button1_Click(object sender, EventArgs e)
            {
                string SearchFor = "abc";
                string SearchIn = "abc123jklabc789yuihjabc789cdsjkleifkbkc125abc";
                List<int> FoundCount = Search(SearchFor, SearchIn);
    
                MessageBox.Show(FoundCount.Count.ToString(), "Count of matches");
            }
    
            List<int> Search(string Target, string Subject)
            {
                List<int> Results = new List<int>();
                for (int Index = 0; Index < (Subject.Length - Target.Length) + 1; Index++)
                {
                    if (Subject.Substring(Index, Target.Length) == Target) Results.Add(Index);
                }
                return Results;
            }

    Comment

    • Bassem
      Contributor
      • Dec 2008
      • 344

      #3
      Hello tlhintoq,

      Thank you for reading my post!

      1. I didn't replace anything in the original string, it is another copy of it.

      2. The main purpose of my post, is to avoid loops in getting the occurrence count of a character in a string.

      Very important idea, that one of counting an occurrence of a string. I think my solution solve this one too, does not it?!

      Finally, what I focused on through my post - again - avoiding loops, but I see one in your solution :)


      Thank you for your interest!

      Comment

      • tlhintoq
        Recognized Expert Specialist
        • Mar 2008
        • 3532

        #4
        Oh... The goal was to avoid loops. Ok. That was never mentioned in the actual post. You even rhetorically ask about using a loop

        I think they have come with working solutions, but how write a method or a loop to do this simple task.

        That is why I asked.

        Comment

        • Bassem
          Contributor
          • Dec 2008
          • 344

          #5
          Forgive my mistake, I wanted to type "why writing" not "how".

          Thanks a lot tlhintoq for reading my posts you give them a value.

          Comment

          • Curtis Rutland
            Recognized Expert Specialist
            • Apr 2008
            • 3264

            #6
            Here's the simplest way I found to do this using LINQ:
            Code:
            int count = "*** test ***".ToCharArray().Where(x => x == '*').Count(); //count == 6
            Technically, there is a loop here that's being obfuscated. The "Where" extension method actually loops through the array for each value (assigning it to "x", the parameter for the method we're shortcutting with a lambda) and stores it in an IEnumerable if the char == '*'. But that's all obfuscated, and what you end up with is a simple one-line code.

            Comment

            • Bassem
              Contributor
              • Dec 2008
              • 344

              #7
              Good idea, and logical than mine!
              I think even my solution the .NET framework uses a loop to replace the occurrence - I've no idea just a thought - but I don't that how I see it simple. Ideally, I was searching for the shortest way to do that.

              Comment

              • GaryTexmo
                Recognized Expert Top Contributor
                • Jul 2009
                • 1501

                #8
                I don't mean to be rude or anything (so please don't read it as such!) but it seems to me that going through all the trouble to eliminate a loop in code by using things that do loops anyway seems a little pointless.

                Don't get me wrong here, using pre-made stuff (ie, the bulk of .NET!) over doing it yourself is great, but you also get disconnected a little from what's going on. I know I sometimes like to expand something just to make sure I'm keeping track of it in my head.

                This is me though, and there's absolutely nothing wrong with the above, I think this thread is a fairly simple case... all I'm saying is just keep in mind the poor individual who gets to come along behind you in a few years and debug your code when you strive to save line space using techniques like this ;)

                Comment

                • Curtis Rutland
                  Recognized Expert Specialist
                  • Apr 2008
                  • 3264

                  #9
                  I do occasionally think about that poor sucker...I mean colleague that may have to read my code.

                  But I guess it's all about style and preference, which should be decided upon and followed at your company. To me, the one-line LINQ statements are easier than the expanded versions, or writing loops and ifs, because they are pretty verbose about what they are doing. They have names like First, Take, and Where. They flow left to right (the same direction you read english).

                  But I don't disagree with you. Sometimes its more efficient to do things all at once together, but it doesn't always lend itself to readability.

                  I just realized how much I have to be seeming like the LINQ guy, because practically all my solutions involve it. It's not that I'm so into it...it's just that it's that darn convenient. Once you learn it, you love it.

                  Comment

                  • jkmyoung
                    Recognized Expert Top Contributor
                    • Mar 2006
                    • 2057

                    #10
                    In the interest of code clarity and re-usability, I would just make it a function:
                    int numberOfCharOcc urrences(String s, char c)
                    then it would look like a clear, one line solution, even though some of the code was elsewhere.

                    Comment

                    • GaryTexmo
                      Recognized Expert Top Contributor
                      • Jul 2009
                      • 1501

                      #11
                      I don't disagree with you either... thus I believe we're in not incomplete non-disagreement!!

                      :P

                      (I just wanted to point that out... I've seen a lot of programmers be obsessed about line count savings. These days, it's just not terribly important imo. Also, I love your LINQ solutions, I learn something almost every post of yours I read. Keep it up!)

                      Comment

                      • Christian Binder
                        Recognized Expert New Member
                        • Jan 2008
                        • 218

                        #12
                        There's a shorter way to do it with LinQ:
                        The count-method takes a predicate to check if an item should be counted, so you can reduce
                        Code:
                        int count = "*** test ***".ToCharArray().Where(x => x == '*').Count(); //count == 6
                        to
                        Code:
                        int count = "*** test ***".ToCharArray().Count(x => x == '*'); //count == 6
                        This would eliminate a loop, because (as far as I know) Where() and Count() will loop over the IEnumerable<cha r>.

                        Comment

                        • Curtis Rutland
                          Recognized Expert Specialist
                          • Apr 2008
                          • 3264

                          #13
                          That's pretty good. I never used count to count a specific character, always just to count total characters. Your way does actually work better.

                          Comment

                          Working...