8

I have a code that I want to count the number of appearing each letter in alphabet in the input string. I used a dictionary<char, int> to have a key for each letter and a value as the count of appearance. So, how to have a list of 'a' to 'z' to use as keys? I've tried this:

Dictionary<char, int> alphabetCounter = new Dictionary<char, int>();
for (char ch = 'a'; ch <= 'z'; ch++)
    alphabetCounter[ch] = 0;

Is it a better way to have the list of 'a' to 'z'? Thank you.

  • 2
    If this wasn't asking for a "better" way (better how?), it would be a duplicate of [Generating an array of letters in the alphabet](https://stackoverflow.com/q/314466/215552) – Heretic Monkey Nov 13 '20 at 21:30
  • Totally opinion based as @HereticMonkey said... If you are looking for the most compact way - `var alphabetCounter = "abc".ToDictionary(keySelector: x=>x, x=>0);` is probably shortest one... also indeed that's pointless as you get result directly anyway with `GroupBy` - https://stackoverflow.com/a/31863230/477420 – Alexei Levenkov Nov 13 '20 at 23:14

4 Answers4

4

Using Linq try this to have a list from "a" to "z".

var list = Enumerable.Range('a', 'z' - 'a' + 1).Select(c => (char)c).ToList();

If you want to get in upper case, is the same but using upper case.

var list = Enumerable.Range('A', 'Z' - 'A' + 1).Select(c => (char)c).ToList();

Edit:

Your question is to get the list, but to get as dictionary you can use .ToDictionary() and initialize with value 0:

var dictionary = Enumerable.Range('a', 'z' - 'a' + 1).Select(c => (char)c).ToDictionary(i => (char)i, i => 0);

The same case to upper/lower case.

J.F.
  • 13,927
  • 9
  • 27
  • 65
  • Thank you man. your answer was the best. –  Nov 14 '20 at 08:24
  • I appreciate if you explain this part ('A', 'Z' - 'A' + 1) of your code for me @J.F. – Roksana Nov 14 '20 at 14:06
  • 5
    'A' and 'Z' are `char` values and [`Enumerable.Range`](https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.range?view=net-5.0) expects integer, so `char` is parsed to `int`. The `int` value is the ASCII code, so the `Enumerable.Range()` con loop through the letters from 'A' to the end, calculated with 'Z' - 'A' +1. If you prefer I edit the question and I try to explain better. – J.F. Nov 14 '20 at 14:25
  • 1
    That's really kind of you @J.F. – Roksana Nov 14 '20 at 14:35
2

Here's a way to do it in LINQ:

var alphabetCounter = Enumerable.Range(97, 26).ToDictionary(i => (char)i, i => 0);

This will create a dictionary with all chars with values 0.

ASCII codes of alphabet (lowercase) begins at 97, we can then take 26 numbers from there and convert them to char.

Haytam
  • 4,643
  • 2
  • 20
  • 43
2

Is performance a thing? You can keep it simple.
You do not need to create your own dictionary, register every possibility then start counter[i]++ for each ocurrence, seems a bit of an overkill to me.

You can group up the letters by using .GroupBy (System.Linq), then after you can check the count of each ocurrence.

Example:

var word = "test";
var groupedLetters = word.GroupBy(x => x);

foreach(var letter in groupedLetters)
{
    Console.WriteLine($"{letter.Key} - {letter.Count()}");
}

Output:

t - 2  
e - 1  
s - 1
Bruno Miquelin
  • 651
  • 1
  • 8
  • 22
1

Hi May this example will help :

List<char> LS = new List<char>() {'A', 'B', 'C', 'D', 'A', 'D', 'B', 'A'};
Dictionary<char,int> AlphaDictionary = (from x in LS group x by x).Select(x => new {Alpha = x.Key, Count = x.Count()}).ToDictionary(x=>x.Alpha,x=>x.Count);
X Dev
  • 97
  • 1
  • 9