我刚创建了一个简单的方法来计算字符串中每个字符的出现次数,而不考虑上限。
static List<int> charactercount(string input)
{
char[] characters = "abcdefghijklmnopqrstuvwxyz".ToCharArray();
input = input.ToLower();
List<int> counts = new List<int>();
foreach (char c in characters)
{
int count = 0;
foreach (char c2 in input) if (c2 == c)
{
count++;
}
counts.Add(count);
}
return counts;
}
是否有更简洁的方法(即不创建字符数组来保存字母表中的每个字符),这也会考虑到数字,其他字符,大写字母等?
答案 0 :(得分:2)
从概念上讲,我宁愿返回Dictionary<string,int>
个计数。我假设可以通过省略而不是显式计数0知道一个字符出现零次,你可以通过LINQ来做。 @Oded给你一个良好的开端,如何做到这一点。您需要做的就是将Select()
替换为ToDictionary( k => k.Key, v => v.Count() )
。请参阅我对他关于进行不区分大小写分组的回答的评论。注意:您应该决定是否关心字符中的文化差异,并相应地调整ToLower
方法。
您也可以在没有LINQ的情况下执行此操作;
public static Dictionary<string,int> CountCharacters(string input)
{
var counts = new Dictionary<char,int>(StringComparer.OrdinalIgnoreCase);
foreach (var c in input)
{
int count = 0;
if (counts.ContainsKey(c))
{
count = counts[c];
}
counts[c] = counts + 1;
}
return counts;
}
请注意,如果您想要Dictionary<char,int>
,可以通过创建案例不变字符比较器并将其用作所需类型字典的IEqualityComparer<T>
来轻松完成此操作。为了简单起见,我在示例中使用了string
。
再次,调整比较器的类型以与您想要处理文化的方式保持一致。
答案 1 :(得分:1)
使用GroupBy
和Select
:
aString.GroupBy(c => c).Select(g => new { Character = g.Key, Num = g.Count() })
返回的匿名类型列表将包含每个字符及其在字符串中出现的次数。
然后,您可以使用Char
上定义的静态方法以您希望的任何方式对其进行过滤。
答案 2 :(得分:0)
您的代码有点慢,因为您循环遍历范围a-z而不是仅仅循环输入。
如果您只需要计算字母(如代码所示),最快的方法是:
int[] CountCharacters(string text)
{
var counts = new int[26];
for (var i = 0; i < text.Length; i++)
{
var charIndex - text[index] - (int)'a';
counts[charIndex] = counts[charindex] + 1;
}
return counts;
}
请注意,您需要添加一些内容,例如验证字符是否在范围内,并在需要时将其转换为小写,否则此代码可能会抛出异常。我会留下那些给你补充的。 :)
答案 3 :(得分:0)
基于+ Ran对避免IndexOutOfRangeException
的回答:
static readonly int differ = 'a';
int[] CountCharacters(string text) {
text = text.ToLower();
var counts = new int[26];
for (var i = 0; i < text.Length; i++) {
var charIndex = text[i] - differ;
// to counting chars between 'a' and 'z' we have to do this:
if(charIndex >= 0 && charIndex < 26)
counts[charIndex] += 1;
}
return counts;
}
实际上使用Dictionary
和/或LINQ
并不足以优化计数字符和使用低级数组。