Reputation:
I'm reading in a text file using StreamReader to the program. I need to record the frequency of each letter in the string into an array (where index 0 would be A, and so on). What's the simplest approach for this?
Edit: I had this originally, until I realized it was completely wrong.
int counter = 0;
int[] freq = new int[26]; // create frequency array
// counts frequency
while (counter < inValue.Length)
{
int A = 65; // ASCII value for "A"
char x = char.Parse(inValue.Substring(counter, 1)); // get individual characters from string
int s = (int)x; // cast character to integer value
if (s == A + counter)
freq[counter]++;
counter++;
}
Where inValue is the text file StreamReader reads into the program.
Upvotes: 2
Views: 6697
Reputation: 39085
var freqs = File.ReadAllText("myfile.txt")
.Where(c => Char.IsLetter(c))
.GroupBy(c => c)
.ToDictionary(g => g.Key, g => g.Count());
This should give you a Dictionary of characters and their count.
Update:
If you want case insensitive counts, just change the GroupBy:
.GroupBy(c => Char.ToUpper(c)) // instead of .GroupBy(c => c)
And in my opinion a dictionary is better than an array in this case because the character that the "count" belongs to is not just implied by the index; instead, it is an explicit key. This makes lookups easier because you don't have to convert the character to an index. Additionally, this makes it more flexible when adding internationalization support. However, if you absolutely need an array, it is a simple change:
var freqs = File.ReadAllText("myfile.txt")
.Where(c => Char.IsLetter(c))
.GroupBy(c => c)
.OrderBy(g => g.Key)
.Select(g => g.Count())
.ToArray()
Upvotes: 6
Reputation: 12420
I spent quite a while to figure out this Linq which will result in the exact same array you want:
int[] occurance = File.ReadAllText("myfile.txt")
.Where(c => char.IsLetter(c))
.Select(c => (int)char.ToUpperInvariant(c) - 65)
.GroupBy(a => a)
.ToDictionary(a => a.Key, a => a.Count())
.OrderBy(a => a.Key)
.Select(a => a.Value)
.ToArray();
Upvotes: 0
Reputation: 133995
A few modifications to your code will make it work, assuming that you only want to count the letters 'A' through 'Z':
int counter = 0;
int[] freq = new int[26]; // create frequency array
// counts frequency
while (counter < inValue.Length)
{
char c = invalue[counter];
if (c >= 'A' && c <= 'Z')
{
++freq[(int)c - 65]
}
++counter;
}
If you want to count lower case letters as well, then change the first line in the loop to:
char c = char.ToUpper(invalue[counter]);
Upvotes: 0
Reputation: 172448
You can try something like this. This worked for me but I didnt used StreamReader:-
int[] c = new int[(int)char.MaxValue];
string s = File.ReadAllText("text.txt");
foreach (char t in s)
{
c[(int)t]++;
}
for (int i = 0; i < (int)char.MaxValue; i++)
{
if (c[i] > 0 &&
char.IsLetterOrDigit((char)i))
{
Console.WriteLine("Letter: {0} Frequency: {1}",(char)i, c[i]);
}
}
Upvotes: 1