0

我想创建每行包含一个名称的文本文件。计算任何名称出现的次数。为文件中的每个名称输出一行,并在每一行打印出现的次数,后跟名称。

我可以使用此代码打开文件

private void button1_Click(object sender, EventArgs e)
{
    using (OpenFileDialog dlgOpen = new OpenFileDialog())
    {
        try
        {
            // Available file extensions
            openFileDialog1.Filter = "All files(*.*)|*.*";
            // Initial directory
            openFileDialog1.InitialDirectory = "D:";
            // OpenFileDialog title
            openFileDialog1.Title = "Open";
            // Show OpenFileDialog box
            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                // Create new StreamReader
                StreamReader sr = new StreamReader(openFileDialog1.FileName, Encoding.Default);
                // Get all text from the file
                string str = sr.ReadToEnd();
                // Close the StreamReader
                sr.Close();
                // Show the text in the rich textbox rtbMain

            }
        }
        catch (Exception errorMsg)
        {
            MessageBox.Show(errorMsg.Message);
        }
    }
}

但我想要的是使用相同的按钮来阅读并在 groupbox 中显示它。

4

5 回答 5

3

由于这是家庭作业,我不会给你代码,但希望有足够的信息为你指明正确的方向。

我建议您使用 File.ReadAllLines 将文件读入字符串数组,数组中的每一项都是文件中的一行。这意味着您不必自己拆分文件内容。然后您可以遍历字符串数组,并将每一行添加到字典中,其中键是从文件中读取的行,值是出现次数。您需要检查键是否已经在字典中 - 如果没有添加它,计数为 1,否则更新现有计数 (+1)。在该循环之后,有第二个循环遍历字典内容,使用名称及其计数更新您的文本框。

于 2012-07-26T09:48:11.617 回答
1

(假设这是一个家庭作业)我使用File.ReadAllLineDictionary<TKey, TValue>

var nameCount = new Dictionary<string, int>();

foreach (String s in File.ReadAllLines("filename"))
{
    if (nameCount.ContainsKey(s))
    {
        nameCount[s] = nameCount[s] + 1;
    }
    else
    {
        nameCount.Add(s, 1);
    }
}

// and printing
foreach (var pair in nameCount)
{
    Console.WriteLine("{0} count:{1}", pair.Key, pair.Value);
}
于 2012-07-26T09:43:18.983 回答
0

您可以使用 Linq 做到这一点,而无需增加int变量。最后有一个包含名称和计数的字典

string names = sr.ReadAllLines();
Dictionary<string, int> namesAndCount = new Dictionary<string, int>();

foreach(var name in names)
{
    if(namesAndCount.ContainsKey(name))
        continue;

    var count = (from n in names
                where n == name
                select n).Count();

    namesAndCount.Add(name, count);
}
于 2012-07-26T10:04:49.917 回答
0

好的,这样的函数将为您构建具有计数的不同名称。

private static IDictionary<string, int> ParseNameFile(string filename)
{
    var names = new Dictionary<string, int>();
    using (var reader = new StreamReader(filename))
    {
        var line = reader.ReadLine();
        while (line != null)
        {
            if (names.ContainsKey(line))
            {
                names[line]++;
            }
            else
            {
                names.Add(line, 1);
            }
            line = reader.ReadLine(); 
        }
    }
}

或者你可以用 linq 和 readAllLines 做一些事情。

private static IDictionary<string, int> ParseNameFile(string filename)
{
    return File.ReadAllLines(filename)
        .OrderBy(n => n)
        .GroupBy(n => n)
        .ToDictionary(g => g.Key, g => g.Count);
}

第一个选项确实具有不将整个文件加载到内存中的优点。

至于输出信息,

var output = new StringBuilder();
foreach (valuePair in ParseNameFile(openFileDialog1.FileName))
{
    output.AppendFormat("{0} {1}\n", valuePair.Key, valuePair.Value); 
}

然后你ToString()在输出上把数据放在你想要的任何地方。如果会有很多行,StreamWriter则首选方法。

于 2012-07-26T09:48:48.007 回答
0

Similar question has been asked before: A method to count occurrences in a list

In my opinion using LINQ query is a good option.

string[] file = File.ReadAllLines(openFileDialog1.FileName, Encoding.Default);

IEnumerable<string> groupQuery =
    from name in file
    group name by name into g
    orderby g.Key
    select g;

foreach (var g in groupQuery)
{
    MessageBox.Show(g.Count() + " " + g.Key);
}
于 2012-07-26T09:41:21.840 回答