我正在使用StreamReader读取文本文件到程序中。我需要将字符串中每个字母的频率记录到一个数组中(其中索引0将是A,依此类推)。对此最简单的方法是什么?
编辑:我最初有这个,直到我意识到这是完全错误的。
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++;
}
其中inValue是文本文件,StreamReader读入程序。
答案 0 :(得分:5)
var freqs = File.ReadAllText("myfile.txt")
.Where(c => Char.IsLetter(c))
.GroupBy(c => c)
.ToDictionary(g => g.Key, g => g.Count());
这应该会给你一个字符词典及其数量。
更新:
如果您想要不区分大小写的计数,只需更改GroupBy:
.GroupBy(c => Char.ToUpper(c)) // instead of .GroupBy(c => c)
在我看来,字典在这种情况下比数组更好,因为“count”所属的字符不仅仅是暗示的索引;相反,它是一个显式键。这使查找更容易,因为您不必将字符转换为索引。此外,这使得在添加国际化支持时更加灵活。但是,如果您绝对需要一个数组,那么这只是一个简单的改变:
var freqs = File.ReadAllText("myfile.txt")
.Where(c => Char.IsLetter(c))
.GroupBy(c => c)
.OrderBy(g => g.Key)
.Select(g => g.Count())
.ToArray()
答案 1 :(得分:1)
你可以尝试这样的事情。这对我有用,但我没有使用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]);
}
}
答案 2 :(得分:0)
对代码进行一些修改会使其工作,假设您只想计算字母'A'到'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;
}
如果您还要计算小写字母,请将循环中的第一行更改为:
char c = char.ToUpper(invalue[counter]);
答案 3 :(得分:0)
我花了很长时间才弄清楚这个Linq会产生你想要的完全相同的数组:
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();