优化字符串中的字符计数
本文关键字:字符 字符串 优化 | 更新日期: 2023-09-27 17:49:30
我刚刚创建了一个简单的方法来计算字符串中每个字符的出现次数,而不考虑大小写。
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;
}
是否有一种更干净的方法来做到这一点(即不创建字符数组来保存字母表中的每个字符),也会考虑到数字,其他字符,大写字母等?
从概念上讲,我更愿意返回计数的Dictionary<string,int>
。我假设通过省略而不是显式计数0来知道字符出现0次是可以的,您可以通过LINQ来实现。@Oded给了你一个很好的开始。你所需要做的就是用ToDictionary( k => k.Key, v => v.Count() )
代替Select()
。请参阅我对他关于不区分大小写分组的回答的评论。注意:您应该决定是否关心字符的文化差异,并相应地调整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
。
同样,调整比较器的类型,使其与您想要处理区域性的方式一致。
使用GroupBy
和Select
:
aString.GroupBy(c => c).Select(g => new { Character = g.Key, Num = g.Count() })
返回的匿名类型列表将包含每个字符及其在字符串中出现的次数。
然后您可以使用Char
上定义的静态方法以任何您希望的方式过滤它。
你的代码有点慢,因为你在循环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;
}
注意,您需要添加一些东西,比如验证字符是否在范围内,并在需要时将其转换为小写,否则这段代码可能会抛出异常。我把这些留给你来补充:)
基于+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
作为计数字符和处理低级数组的优化还不够。