0

I have String called "RamaSubbaReddyabcdaacacakkkoooahgafffgahgghsa". I want to know number of "a" characters available in the give String. As per my knowledge I found two ways to find the count. That are: 1) By using String.Split() 2) Linq Lambda Expression

My Observations:

1) If i use String.Split() it is returning wrong result 2) If i use Linq Lambda Expression it is returning correct result.

Here my doubt is how can i get the count of the given split character from the given string by using String.Split()

And also please suggest me which is the best way to get count of the given split character from the given string either "String.Split()" or "Linq Lambda" expression?

Please find the complete example:

                                                                                                                   using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SplitData
{
    class Program
    {
        static void Main(string[] args)
        {
            SplitData("RamaSubbaReddyabcdaacacakkkoooahgafffgahgghsa", 'a');
            SplitData("RamaSubbaReddyabcdaacacakkkoooahgafffgahgghsa", 'r');
            SplitData("RamaSubbaReddyabcdaacacakkkoooahgafffgahgghsa", 'R');
            SplitData("RamaSubbaReddyabcdaacacakkkoooahgafffgahgghsa", 'm');
            SplitData("RamaSubbaReddyabcdaacacakkkoooahgafffgahgghsa", 'd');
            SplitData("RamaSubbaReddyabcdaacacakkkoooahgafffgahgghsa", 'g');
            SplitData("RamaSubbaReddyabcdaacacakkkoooahgafffgahgghsa", 's');
            SplitData("RamaSubbaReddyabcdaacacakkkoooahgafffgahgghsa", 'o');
            SplitData("RamaSubbaReddyabcdaacacakkkoooahgafffgahgghsa", 'c');
            SplitData("RamaSubbaReddyabcdaacacakkkoooahgafffgahgghsa", 'u');
            SplitData("RamaSubbaReddyabcdaacacakkkoooahgafffgahgghsa", 'f');


            Console.ReadKey();
        }

        private static void SplitData(string data,char split)
        {

            // using lambda expresion
            int len = data.AsEnumerable().Where(x => x.ToString().ToLower().Contains(split)).Count();  
            Console.WriteLine("Total '" + split + "' available are:{0} using lambda", len.ToString());

            //using normal split function
            len = data.Split(split).Length;

            Console.WriteLine("Total '" + split + "' available are:{0} using normal split", len.ToString());


        }
    }
}
  • 2
    possible duplicate of [How would you count occurrences of a string within a string (C#)?](http://stackoverflow.com/questions/541954/how-would-you-count-occurrences-of-a-string-within-a-string-c) – Jon Oct 04 '13 at 15:24
  • Those two functions are not equivalent. In the first you take String.ToLower() in the second you take the string "as is". – Ed Charbeneau Oct 04 '13 at 15:26
  • Hi Jon. This not a duplicate question of http://stackoverflow.com/questions/541954/how-would-you-count-occurrences-of-a-string-within-a-string-c. Please read question carefully before telling as a duplicate question.. because i am asking is: >>>>>> refer it in above question Here my doubt is how can i get the count of the given split character from the given string by using String.Split() And also please suggest me which is the best way to get count of the given split character from the given string either "String.Split()" or "Linq Lambda" expression? – Rama Subba Reddy M Oct 04 '13 at 15:30
  • 1
    @RamaSubbaReddyM: the linked question addresses shows how to do it with String.Split(), and discusses which option is "best". It is a duplicate. – Colin DeClue Oct 04 '13 at 15:49

4 Answers4

7
string str = "RamaSubbaReddyabcdaacacakkkoooahgafffgahgghsa";
int countA = str.Count(r => r == 'a');

If you want case insensitive count then:

string str = "RamaSubbaReddyabcdaacacakkkoooahgafffgahgghsa";
char searchChar = 'a';
int countA = str.Count(r => char.ToUpperInvariant(r) == char.ToUpperInvariant(searchChar));

If you ask for best option between string.Split and Linq Count, then IMO, LINQ is more readable. I am not sure about the performance but I suspect LINQ version to be faster.


If you want to use string.Split and make it case insensitive then construct a character array of two elements, (with upper case and lower case) and then use Split like:

string str = "RamaSubbaReddyabcdaacacakkkoooahgafffgahgghsa";
char searchChar = 'a';
char[] delimeters = new char[2];
delimeters[0] = char.ToLowerInvariant(searchChar);
delimeters[1] = char.ToUpperInvariant(searchChar);
var count = str.Split(delimeters).Length - 1;
Habib
  • 219,104
  • 29
  • 407
  • 436
  • Hi Habib,how can i get the count of the given split character from the given string by using String.Split()?. I am already getting correct count by using linq concepts. – Rama Subba Reddy M Oct 04 '13 at 15:32
  • @RamaSubbaReddyM `data.Split(split).Length - 1` (Note this is case sensitive) – jdl Oct 04 '13 at 15:33
  • @RamaSubbaReddyM, you can do `var count = str.Split(new[] { 'a', 'A' }).Length - 1;` but you have to construct an array of upper case and lower case character to make it case insensitive. – Habib Oct 04 '13 at 15:37
  • I'm having a hard time understanding the difference (in results at least) between using `Count` and using `Split` and then counting the size of the split set. Won't that return the exact same count? – sircodesalot Oct 04 '13 at 15:40
  • 1
    @RamaSubbaReddyM, I just updated my answer which is using `string.Split` to count occurrence of a char *(case insensitive)* – Habib Oct 04 '13 at 15:44
  • @Habib, Thanks for solutions. There was a small issue in your solution. If i use StringSplitOptions.RemoveEmptyEntries i am getting wrong result otherwise getting correct result. Example: data.Split(new char[] { char.ToLowerInvariant(split), char.ToUpperInvariant(split) },StringSplitOptions.RemoveEmptyEntries).Length - 1; – Rama Subba Reddy M Oct 04 '13 at 15:47
  • @Habib, Suppose i want to remove empty data what will happen?. any how thanks for the solution.. – Rama Subba Reddy M Oct 04 '13 at 15:53
  • @RamaSubbaReddyM, if you remove empty data, you will not get the correct count, since `Adjacent delimiters yield an array element that contains an empty string ("")` Read more about [`StringSplitOptions.RemoveEmptyEntries`](http://msdn.microsoft.com/en-us/library/system.stringsplitoptions.aspx). So if there are adjacent `a` in your string, `RemoveEntrieis` would give you wrong result. – Habib Oct 04 '13 at 15:55
  • I would turn the input string to `lower case` and then use `Split('a')` only without having to care about `'a' or 'A'` – King King Oct 04 '13 at 15:57
2

You mean you want to count the occurances of a letter? Like this?

String data = "RamaSubbaReddyabcdaacacakkkoooahgafffgahgghsa";
Char letter = 'a';
Int32 totalOccurances = data.Count(character => character == letter);
sircodesalot
  • 11,231
  • 8
  • 50
  • 83
2

For case-insensitive comparison, you can use a StringComparer instance or equivalent StringComparison enum.. As far as how you want to write it, pick your poison. =)

// caller specifies comparison type
int Count1(string str, char searchChar, StringComparison comparison = StringComparison.CurrentCultureIgnoreCase)
{
    string searchStr = searchChar.ToString();
    int count = 0;
    for (int i = 0; i < str.Length; i++)
        if (string.Equals(searchStr, str[i].ToString(), comparison))
            count++;
    return count;
}
// ordinal comparison
int Count2(string str, char searchChar)
{
    string searchStr = searchChar.ToString();
    int count = 0;
    for (int i = 0; i < str.Length; i++)
        if (searchChar == str[i])
            count++;
    return count;
}
// ordinal comparison
int Count3(string str, char searchChar)
{
    return str.Split(searchChar).Length - 1;
}
// ordinal comparison
int Count4(string str, char searchChar)
{
    return str.Count(c => c == searchChar);
}
// caller specifies comparison type
int Count5(string str, char searchChar, StringComparison comparison = StringComparison.CurrentCultureIgnoreCase)
{
    string searchStr = searchChar.ToString();
    return str.Count(c => string.Equals(c.ToString(), searchStr, comparison));
}
Tim S.
  • 55,448
  • 7
  • 96
  • 122
1

Not a fancy LINQ solution but nevertheless

int count = CountChar("RamaSubbaReddyabcdaacacakkkoooahgafffgahgghsa", 'a');
.....

int CountChar(string input, char toFind)
{
    int count = 0;
    int pos = -1;
    while((pos = input.IndexOf(toFind, pos+1)) != -1)
        count++;
    return count;
}

String.IndexOf starting from a position
and there is also the case insensitive option

EDIT: Well now I was curious and decided to measure the timing with this and the lambda solution.
The difference is remarkable.....

void Main()
{
    string str = "RamaSubbaReddyabcdaacacakkkoooahgafffgahgghsa";
    Stopwatch sw = new Stopwatch();
    sw.Start();
    for(int i = 0; i < 10000000; i++)
    {
        int count = CountChar(str, 'a');
     }   
    sw.Stop();
    Console.WriteLine("Using IndexOf:" + sw.ElapsedMilliseconds.ToString());  
    sw.Reset();
    sw.Start();
    for(int i = 0; i < 10000000; i++)
    {
        int countA = str.Count(r => r == 'a');
    }
    sw.Stop();
    Console.WriteLine("Using Count:" + sw.ElapsedMilliseconds.ToString());
}

The first loop ends in 1160 milliseconds and the second one in 6200 milliseconds.
Can someone spot if there are problems in this measurements?

Steve
  • 213,761
  • 22
  • 232
  • 286
  • Well this is MUCH better than splitting a string at the char and building an array of strings. Not sure if it is more performant than the LINQ solutions proposed, but with these strings it is a real micro difference – Steve Oct 04 '13 at 15:35
  • 1
    This is actually potentially faster, since there is no lambda callback on each iteration. So that will save you *at least* one-billionth of a second. Maybe even two! – sircodesalot Oct 04 '13 at 15:35
  • 1
    (Regarding your edit) Yeah, that's about what I would've expected. Recusion/Lambdas are useful in that they simplify the program conceptually, but they certainly don't do you any performance favors. They do open up the way towards parallel solutions though.... – sircodesalot Oct 05 '13 at 16:14