这是使用LINQ创建频率表的最佳方法吗?

时间:2010-07-14 09:48:57

标签: c# linq

我想编写一个读取文件的函数,并计算每个单词出现的次数。假设处理文件读取并生成表示文件中每一行的字符串列表,我需要一个函数来计算每个单词的出现次数。首先,使用Dictionary<string,int>最好的方法?关键是单词,值是该单词的出现次数。

我编写了这个函数,它遍历每一行和一行中的每个单词并构建一个字典:

static IDictionary<string, int> CountWords(IEnumerable<string> lines)
var dict = new Dictionary<string, int>();
foreach (string line in lines)
{
    string[] words = line.Split(' ');
    foreach (string word in words)
    {
        if (dict.ContainsKey(word))
            dict[word]++;
        else
            dict.Add(word, 1);
    }
}

但是,我想以某种方式编写这个函数..功能上,使用LINQ(因为LINQ很有趣,我正在努力提高我的函数编程技能:D)我设法得出这个表达式,但我'我不确定这是否是在功能上做到最好的方式:

static IDictionary<string, int> CountWords2(IEnumerable<string> lines)
{
    return lines
        .SelectMany(line => line.Split(' '))
        .Aggregate(new Dictionary<string, int>(),
            (dict, word) =>
            {
                if (dict.ContainsKey(word))
                    dict[word]++;
                else
                    dict.Add(word, 1);
                return dict;
            });
}

因此,虽然我有两个有效的解决方案,但我也有兴趣了解最佳方法对此问题的影响。谁有洞察LINQ和FP的人?

4 个答案:

答案 0 :(得分:7)

正如Tim Robinson所写,你可以GroupBy使用ToDictionary这样的

    public static Dictionary<string, int> CountWords3(IEnumerable<string> strings)
    {
        return strings.SelectMany(s => s.Split(' ')).GroupBy(w=>w).ToDictionary(g => g.Key, g => g.Count());
    }

答案 1 :(得分:3)

查看GroupBy而不是Aggregate - 它会为您提供一组IGrouping<string, string>个对象。您可以通过在每个分组上调用.Count()来检索每个单词的计数。

答案 2 :(得分:3)

以下应该做的工作。

static IDictionary<String, Int32> CountWords(IEnumerable<String> lines)
{
    return lines
        .SelectMany(line => line.Split(' '))
        .GroupBy(word => word)
        .ToDictionary(group => group.Key, group => group.Count());
}

答案 3 :(得分:0)

如果你想使用linq(而不是使用linq firectly使用的扩展方法)你可以写:

var groups = from line in lines
             from s in line.Split(new []{"\t", " "},StringSplitOptions.RemoveEmptyEntries) 
             group s by s into g
             select g;
var dic = groups.ToDictionary(g => g.Key,g=>g.Count());

您当前的实现不会在标签上拆分,并且可能包含“word”字符串。这样我就根据我的想法更改了拆分。