我想编写一个读取文件的函数,并计算每个单词出现的次数。假设处理文件读取并生成表示文件中每一行的字符串列表,我需要一个函数来计算每个单词的出现次数。首先,使用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的人?
答案 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”字符串。这样我就根据我的想法更改了拆分。