2012-12-31 30 views
6

我有csv文件與30 000行。我必須根據許多條件選擇許多值,所以許多循環都被忽略了,「if」我決定使用linq。我已經寫了課,讀csv。它實現了IEnumerable與linq一起使用。這是我的調查員:是否可以更改LINQ中的搜索方法?

class CSVEnumerator : IEnumerator 
{ 

    private CSVReader _csv; 

    private int _index; 

    public CSVEnumerator(CSVReader csv) 
    { 
     _csv = csv; 
     _index = -1; 
    } 

    public void Reset(){_index = -1;} 


    public object Current 
    { 
     get 
     { 
      return new CSVRow(_index,_csv); 
     } 
    } 


    public bool MoveNext() 
    { 
     return ++_index < _csv.TotalRows; 
    } 

} 

它的工作,但它很慢。假設我想在列100中選擇列A中的最大值; 150行。

max = (from CSVRow r in csv where r.ID > 100 && r.ID < 150 select r).Max(y=>y["A"]); 

這是可行的,但在30個000行,而不是48 正如我所說的,我可以用循環,但只有在這個例子的情況下,條件是「殘酷」的最大值LINQ搜索:)

有什麼方法可以重寫linq集合搜索。類似於:查看我的枚舉器上使用的查詢,看看「where」中是否包含「row ID filter」的任何linq條件,並根據此情況提供另一個數據。

我不想將部分數據複製到另一個數組/集合,問題不在我的csv閱讀器中。通過id訪問每一行很快,唯一的問題是當你訪問所有30 000個。 任何幫助appriciated :-)

+1

順便說一句,你應該實現'IEnumerable '。 – SLaks

+0

這是如何實現的 - >'新的CSVRow(_index,_csv)'。隨機訪問還是順序訪問? – Tilak

+1

是否確定linq to objects將Max應用於所有記錄,而不僅僅是這48個?奇怪的是,它應該按順序應用運營商。我的猜測是你的調查員只是很慢。 –

回答

2

如果您希望能夠有效地使用LINQ,那麼您需要使用expression trees,與SQL數據庫的各種LINQ提供程序相似(但更簡單)。雖然可行,但我認爲對於這樣一個簡單的任務來說,這將是相當多的代碼。因此,我認爲更好的解決方案是使用單獨的方法來選擇所需的行(然後可能使用LINQ來處理結果)。

此外,許多返回集合的操作(包括您的原始代碼和我的修改)可以通過使用iterator methods來簡化。

所以,你的代碼可能是這個樣子:

public static IEnumerable<CSVRow> GetRows(
    this CSVReader reader, int idGreaterThan, int idLessThan) 
{ 
    for (int i = idGreaterThan + 1; i < idLessThan; i++) 
    { 
     yield return new CSVRow(reader, i); 
    } 
} 

在這裏,它是CSVReader擴展方法,但另一種解決方案(例如,在該類實際方法)可能更適合您。

你的榜樣,然後將類似:

max = csvReader.GetRows(100, 150).Max(y => y["A"]); 

(另外,我覺得很奇怪,當你有限制100和150,你居然要101和149之間的行,但我假設你有一個原因,所以我也是這樣做的。)

+0

這正是我所需要的,謝謝你:-) 100和150只是一個示例來顯示問題,如果我發佈實際條件,我將不得不解釋變量來自哪裏,哪些數據類型等等。 –

1

就LINQ而言,r.ID是一個簡單的值被過濾,所以所有30k行被認爲是用於最大操作。如果這是一個行索引,這似乎是這種情況,您可以使用Skip和Take來避免比較所有30k行。

max = csv.Skip(100).Take(50).Max(y => y["A"]); 
+0

但是這仍然會迭代150行,而不是50.所以,如果範圍是29000-29050,那麼您將迭代29050行,這是非常無效的。 – svick

+0

@svik:如果你跳過第一個29000,你的CSVReader如何知道他是哪一行?您仍然需要閱讀所有這些,以便選擇正確的行。我猜CSVReader實現效率不高。它應該緩存已經讀取的行,然後幾乎所有的查詢都會很快。 –

+0

@AloisKraus我不知道如何實現'CSVReader',但問題是它有效地檢索任何單行。 – svick

0

@DougM是對有關評價的順序,但在這種情況下,我會做的是採取一次性打在初始化和查找產生任何「指數」字段:基本上,預先計算的地圖(字典)的行索引。也就是說,如果您對給定的索引字段有許多重複的查詢,這隻會很有用。

相關問題