遍历string并计算出现次数

本文关键字:计算 string 遍历 | 更新日期: 2023-09-27 18:12:56

这就是问题所在:

    编写一个程序,从控制台读取一个字符串,并按字母顺序打印输入字符串中的所有字母以及每个字母在字符串中出现的次数。

一开始似乎很有趣,也不太复杂,但我解不出来。

public static void Letters()
{
        string input;
        Console.Write("Enter a string:  ");
        input = Console.ReadLine();
        var chars = new List<char>();
        //To populate characters with the letters of the input but without repetition
        for(int index = 0; index < input.Length; index++)
        {
            if(!characters.Contains(input[index]))
                characters.Add(input[index]);
        }
        //To increment the counter corresponding to the character index
        int[] counter = new int[characters.Count];

        //Now what ?!
    }

我的想法是:

我创建了一个集合来保存输入字符串的字母,没有任何重复。

然后使用大小相同的int数组,使每个int保存相应字母在输入字符串中出现的次数。

我不仅不知道如何实现这个,但我有一种感觉,这不是一个理想的解决方案解决问题。可能有一个查询或lambda表达式可以使这变得容易实现和读取。

注意:下面的问题性质相同。不同之处在于它提出了要求用单个字母"aaabbbccc"代替重复字母"abc"。

如果逻辑被描述,我会很感激。我会试着自己实现它,告诉我逻辑是什么。

编辑:

这是我用字典的答案

public static void Letters()
{
        string input;
        Console.Write("Enter a string:  ");
        input = Console.ReadLine();
        var dict = new Dictionary<char, int>();
        for(int index = 0; index < input.Length; index++)
        {
            char theKey = input[index]; //just for clarity
            if(!dict.ContainsKey(theKey))
                dict.Add(theKey, 1);
            else
                dict[input[index]]++;
        }
        foreach(var key in dict.Keys)
        {
            Console.WriteLine("{0}'t{1}", key, dict[key]);
        }

遍历string并计算出现次数

Dictionnary<String, int>

Key = string =字母IE a,b,c,d,e,f.....Int是出现次数

那么从这样开始:

Dictionnary.add(a,0)
...
Dictionnary.add(z,0);

然后读取字符串并执行

Dictionnary[letterFound ] += 1;

有一种更好的方法可以知道每个字母的ascii值来初始化字典,但我认为对于这种练习不是必须的。

好运

var myString = "Hello";
var dict = new Dictionary<char, int>();
foreach(var c in myString)
{
    if(!dict.ContainsKey(c))
        dict.Add(c, 1);
    else
        dict[c]++;
}
var orderedDict = dict.OrderBy(x => x.Key);
foreach(var kvp in orderedDict)
{
    Console.WriteLine("Letter: {0}, Times: {1}", kvp.Key, kvp.Value);
}

对于简单易读的解决方案,请使用LINQ, GroupBy和匿名类型

string input = Console.ReadLine();
var groupedLettersOrdered = input.GroupBy(x => x, (character, charCollection) =>
    new {Character = character, Count = charCollection.Count()})
    .OrderBy(x => x.Character);
foreach(var letterGroup in groupedLettersOrdered)
    Console.WriteLine("Character {0}, Count: {1}", letterGroup.Character, letterGroup.Count);

然而,Dictionary<char, int>解决方案将(应该)更快,更好的大字符串

首先考虑一个字符具有二进制表示(1和0的序列),就像标量值一样。还考虑对于像英语这样的拉丁字母,其对应的字母顺序和数字顺序是相对应的。

所以…你可以这样做:

  1. 定义一个足够大的整数数组,其大小足以容纳所有可能的字符值(任意,我们可以为UTF-8字符串设置256)。
  2. 遍历字符串中的每个字符;对于每个字符,将字符转换为其等效的整数,将其用作数组的索引,并在该索引处增加值。
  3. 遍历数组,对于每个非零元素,打印出数组索引的等效字符和元素的内容(字符计数)

        string myString = "the quick brown fox jumps over the lazy dog";
        byte[] bytes = Encoding.UTF8.GetBytes(myString);
        int[] counts = new int[256];
        foreach (var b in bytes)
        {
            counts[(int)b]++;
        }
        for (int i = 0; i < 256; i++)
        {
            if (counts[i] > 0)
            {
                Console.WriteLine("{0} - {1}", (char)(byte)i, counts[i]);
            }
        }
    

通过对myString.ToUpper()执行GetBytes,可以很容易地将上述解决方案推广为忽略大小写。要泛化到Unicode将需要更多的工作,因为您必须以正确的端序对字节进行配对。