2010-11-07 65 views
3

關於this solutionLinq關鍵字提取 - 限制提取範圍

有沒有辦法限制要考慮的關鍵字數量?例如,我只想計算前1000個字的文字。 Linq中有一個「Take」方法,但它有不同的用途 - 所有的單詞都將被計算,並且N個記錄將被返回。什麼是正確的選擇,使其正確?

+0

'以()'就是一個懶惰功能!它並沒有使所有的單詞都被計算出來。例如,請參閱http://ideone.com/WwDwg。 – Vlad 2010-11-07 12:25:00

回答

2

簡單地套用Take更早 - 呼叫後直奔Split

var results = src.Split() 
       .Take(1000) 
       .GroupBy(...) // etc 
+0

簡單的解決方案,但似乎對我的情況很好。謝謝喬恩! – SharpAffair 2010-11-08 12:37:17

1

Enumerable.Take是否確實流出來的結果;它不會完全緩衝其源,然後只返回第一個N.但是,看看您的原始解決方案,問題是輸入到您想要執行Take的輸入是String.Split。不幸的是,這種方法不使用任何延遲執行;它急切地創建一個所有'分割'的數組,然後返回它。

因此,從一些文字得到單詞的流序列的技術會是這樣的:

var words = src.StreamingSplit() // you'll have to implement that    
       .Take(1000); 

不過,我注意到,您的查詢的其餘部分是:

... 
.GroupBy(str => str) // group words by the value 
.Select(g => new 
      { 
       str = g.Key,  // the value 
       count = g.Count() // the count of that value 
       }); 

請注意,GroupBy是一個緩衝操作 - 您可以預計,源自它的1,000個單詞中的所有單詞最終都將被存儲在正在管理的組的過程中的某個位置。

在我看來,有三種選擇:

  1. 如果你不介意通過所有的文字去爲分裂目的,那麼src.Split().Take(1000)是罰款。缺點是浪費時間(在不再需要時繼續分裂)和浪費空間(即使只有前1000個,將所有單詞存儲在數組中)。但是,查詢的其餘部分將不會以超出必要的字數操作。
  2. 如果由於時間/內存限制您無法承擔(1),請使用src.StreamingSplit().Take(1000)或同等產品。在這種情況下,在找到1000個單詞後,沒有任何原始文本會被處理。

請注意,這些1000個字自己會最終得到通過在兩種情況下GroupBy條款緩衝。

+0

感謝您的詳細回覆。 – SharpAffair 2010-11-08 12:38:22

1

那麼,嚴格來說LINQ是而不是一定要去讀一切;採取將盡快停止。問題是,在相關問題中,您看看Count,並且很難在不消耗所有數據的情況下獲得Count。同樣,string.Split將會查看的所有內容

但是,如果你寫了一個懶惰的非緩衝分割功能(使用收益回報),你想第一個1000分獨特的話,那麼

var words = LazySplit(text).Distinct().Take(1000); 

會工作