优化字符串中的字符计数

本文关键字:字符 字符串 优化 | 更新日期: 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

同样,调整比较器的类型,使其与您想要处理区域性的方式一致。

使用GroupBySelect:

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作为计数字符和处理低级数组的优化还不够。