-2

Hi all i have a small function that is storing characters in a string into a dictionary. The string could contain lower case and upper case letters simultaneously and I wanted to store all the characters in either lower case or upper case. Basically i want the dictionary to treat 'T' and 't' as same key. Below is my code.

public bool CheckCharOddCount(string str1)
{
  bool isOdd = false;
  Dictionary<char, int> dt = new Dictionary<char, int>();

  // Dictionary is case sensitive so 'T' and 't' are treated as different keys.       
  str1 = str1.ToLower();  # One way 
  foreach (char c in str1) 
  {
    c = char.ToLower(c);      # Another way
    if (dt.ContainsKey(c))
      dt[c]++;
    else
      dt.Add(c, 1);
  }

  foreach (var item in dt)
  {
    if (item.Value % 2 == 1)
    {
      if (isOdd)
        return false;
      isOdd = true;
    }
  }

  return true;
}

Now I tried to do couple of things here, like converting the input string to lower case as one way or to lower case each character inside for loop.

The first way of lower casing the string works fine, but I am modifying the immutable string object so may not be efficient way of doing. My second way is working but I am not sure if that is efficient in case of a large string.

Any comments on making my dictionary case insensitive or lower casing the string in most efficient way??

Naphstor
  • 2,356
  • 7
  • 35
  • 53
  • 5
    Stop now, and before you use 'ToLower', go and read http://haacked.com/archive/2012/07/05/turkish-i-problem-and-why-you-should-care.aspx/ and https://blog.codinghorror.com/whats-wrong-with-turkey/ – Remus Rusanu Oct 25 '16 at 16:19
  • You'd have to do `c = char.ToLower(c);` for that to work. – juharr Oct 25 '16 at 16:28

2 Answers2

1

To create a case insensitive key dictionary, use the appropriate constructor:

Dictionary<string, int> dictionary = new Dictionary<string, int>(
        StringComparer.CurrentCultureIgnoreCase);
Alsty
  • 817
  • 10
  • 23
Remus Rusanu
  • 288,378
  • 40
  • 442
  • 569
  • 1
    We don't have enough information to know whether the strings are culturally sensitive or not, but the answer is likely to be either CurrentCultureIgnoreCase or OrdinalIgnoreCase. Using InvariantCulture is normally an error. See http://stackoverflow.com/questions/492799/difference-between-invariantculture-and-ordinal-string-comparison – Alsty Oct 25 '16 at 16:26
  • @PsychomaticComplexity you are correct, I fixed it. – Remus Rusanu Oct 25 '16 at 16:27
-1

If you're dealing with english only, this oneliner will do the job:

string s = "AaaaAcWhatever";
Dictionary<char, int> dic = s.GroupBy(c => char.ToLower(c))
                             .Select(g => new { Key = g.Key, Count = g.Count()})
                             .ToDictionary(x => x.Key.First(), x => x.Count);

Output:

Count = 8
[0]: {[a, 6]}
[1]: {[c, 1]}
[2]: {[w, 1]}
[3]: {[h, 1]}
[4]: {[t, 1]}
[5]: {[e, 2]}
[6]: {[v, 1]}
[7]: {[r, 1]}
Thomas Ayoub
  • 29,063
  • 15
  • 95
  • 142