优化字符串中的计数字符

时间:2012-12-22 19:09:28

标签: c# string performance character

我刚创建了一个简单的方法来计算字符串中每个字符的出现次数,而不考虑上限。

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;

        }

是否有更简洁的方法(即不创建字符数组来保存字母表中的每个字符),这也会考虑到数字,其他字符,大写字母等?

4 个答案:

答案 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)

使用GroupBySelect

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并不足以优化计数字符和使用低级数组。