2010-07-14 43 views
4

我想寫一個函數來讀取一個文件並計算每個單詞出現的次數。假設處理文件讀取併產生表示文件中每行的字符串列表,我需要一個函數來計算每個單詞的出現次數。首先,是使用Dictionary<string,int>最好的方法?關鍵是這個詞,值是該詞出現的次數。這是使用LINQ創建頻率表的最佳方式嗎?

我寫了這個函數遍歷在一條線上每一行和每一字,並建立了一個字典:

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)我設法想出這個expresion,但我不知道它是否做到這一點功能的最佳方式:

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; 
      }); 
} 

所以雖然我有兩個工作解決方案,但我也對lea感興趣最好採用什麼方式來解決這個問題。任何有洞察LINQ和FP的人?

回答

6

蒂姆·羅賓遜寫道,你可以使用GroupByToDictionary這樣

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()); 
    } 
+0

從技術上說,這不是通過使用語言集成查詢,但通過使用一些擴展方法LINQ是建立在(但是然後OP是要求LINQ,但使用擴展方法,所以這可能是他要求的任何:)) – 2010-07-14 10:37:03

+2

@Rune FS:這一切LINQ,以及個人喜好的問題,無論您使用查詢理解語法還是擴展方法語法。 (事實上​​,有些查詢只能用擴展方法語法來表示,你會聲稱這些查詢不是LINQ嗎?) – LukeH 2010-07-14 10:43:02

+1

@Rune FS:我想他是在尋求像這樣的事情。 。正如LukeH指出的那樣,這都是LINQ。 – 2010-07-14 10:47:29

3

看看GroupBy而不是Aggregate - 它會給你一組IGrouping<string, string>對象。您可以通過在每個分組上撥打.Count()來檢索每個詞的計數。

+1

順便說一句,既然你說你有興趣學習,我沒有發佈確切的代碼:) – 2010-07-14 10:24:38

+0

謝謝,你的提示幫助我玩更多的東西,得到更好的東西:) – guhou 2010-07-14 11:08:29

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()); 
} 
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()); 

您當前的實現將不會在標籤分裂,可能包括「單詞「string.Empty所以我已經根據我認爲你的意圖改變了分裂。