【问题标题】:File reading and words counting文件阅读和单词计数
【发布时间】:2021-12-10 13:09:11
【问题描述】:

我想读取一个文件,然后读取一串单词或一个句子,并分别计算这些单词在文件中出现的次数。我还需要将不出现的单词分开。
示例输入
filename.txt
Powerfull moon forest sky
示例输出
强大:2
月亮:3
森林:4
未使用:天空
我有点卡在这里,这就是我得到的

string filename = Console.ReadLine();
        StreamReader stream = File.OpenText(filename);
       
        string input = Console.ReadLine();
        string[] source = filename.Split(new char[] { '.', '?', '!', ' ', ';', ':', ',' }, StringSplitOptions.RemoveEmptyEntries);
        var matchQuery = from word in source
                         where word.ToLowerInvariant() == input.ToLowerInvariant()
                         select word;
        int wordCount = matchQuery.Count();
        Console.WriteLine("{0} occurrences(s) of the search term \"{1}\" were found.", wordCount, input);

【问题讨论】:

标签: c#


【解决方案1】:

有几种方法可以做到这一点。其中之一是按照 Arshad 评论的查询分组。如果您逐行读取文件,您还可以使用字典来保存结果。这是示例,但您必须根据自己的要求对其进行调整:https://stackoverflow.com/a/11967649/7226070

【讨论】:

    【解决方案2】:

    不要拆分空格和标点符号(请注意,我们有很多空格) 我建议匹配。如果我们将 word 定义为

    单词是非空的字母序列

    我们可以使用一个简单的正则表达式模式:

     \p{L}+
    

    然后你可以预处理文件:

     using System.IO;
     using System.Linq;
     using System.Text.RegularExpressions;
    
     ...
    
     Regex regex = new Regex(@"\p{L}+");
    
     var freqs = File
       .ReadLines(filename)
       .SelectMany(line => regex
          .Matches(line)
          .Cast<Match>()
          .Select(match => match.Value))
       .GroupBy(word => word, StringComparer.OrdinalIgnoreCase)
       .ToDictionary(group => group.Key, group => group.Count());
    

    用户查询时间。同样,我们匹配单词,然后在 freqs 的帮助下找到出现的情况:

      var result = regex
        .Matches(Console.ReadLine())
        .Cast<Match>()
        .Select(match => match.Value)
        .Distinct(StringComparer.OrdinalIgnoreCase)
        .Select(word => 
           (word : word, 
            count : (freqs.TryGetValue(word, out int count) ? count : 0))) 
        .OrderBy(item => item.count == 0) // push all not used to the end
        .GroupBy(item => item.count > 0 ? item.word : "Not used")
        .Select(group => $"{group.Key} : {string.Join(", ", group)}"); 
    
      Console.Write(string.Join(Environment.NewLine, result));
    

    【讨论】:

    • 我在尝试使用此代码时遇到错误:.Select(word => $"{(freqs.TryGetValue(word, out int count) ? count : 0)} 出现次数{word} 找到");
    • @Aleksandar Yordanov:我的错,很抱歉打错了,第一个片段应该是.ToDictionary(group =&gt; group.Key, group =&gt; group.Count());
    • 这真的很好,但是如果我想要一个“未使用”字符串并将所有未找到的单词放在其中而不是显示为 0 怎么办?
    • @Aleksandar Yordanov:你所要做的就是改变最后一点Select:.Select(word =&gt; freqs.TryGetValue(word, out int count) ? $"{count} occurrences(s) of {word} found" : "Not used");
    • 它不完全是我需要的,输出应该是,我需要知道哪个单词没有被使用而不是空值示例输出:强大:2 月亮:3 森林:4 未使用: 天空
    猜你喜欢
    • 1970-01-01
    • 2016-12-08
    • 1970-01-01
    • 2015-06-02
    • 2015-06-09
    • 2021-07-17
    • 2023-03-18
    • 2016-08-06
    • 1970-01-01
    相关资源
    最近更新 更多