2009-08-17 58 views
3

我有一個包含一些CSV結構如下簡單的文本文件:使用LINQ查詢的文本文件

@Parent1_Field1, Parent1_Field2, Parent1_Field3 
Child1_Field1, Child1_Field2 
Child2_Field1, Child2_Field2 
...etc. 
@Parent2_Field1, Parent2_Field2, Parent2_Field3 
Child1_Field1, Child1_Field2 
Child2_Field1, Child2_Field2 
...etc. 

「@」,指示子對象的父對象,它會立即在其下方。 (這可以使用XML更好地表示,但這不是我的選擇。)

我的目的是使用LINQ查詢此文件而不將其全部內容加載到內存中。首先,我創建了一個實現IEnumerable的類(這裏是:MyCustomReader),其中我使用StreamReader來獲取文件的每一行。

E.g.下面得到所有的父對象(不帶小孩):

from line in MyCustomReader 
where line.StartsWith("@") 
select Parent.Create(line) 

然而,當我想創建涉及Parent和Child對象的查詢我被困。例如,讓一個特定父對象的所有子對象或獲取特定childfield包含相同值的所有父對象。

E.g.這得到所有特定父對象的孩子:

public IEnumerable<Child> GetChildrenForAParent(string uniqueParentName) 
{ 
    Parent parent = null; 
    foreach (string line in MyCustomReader) 
    { 
     if (line.StartsWith("@")) 
      parent = Parent.Create(line); 
     else if (parent.UniqueName == uniqueParentName) 
      yield return Child.Create(line); 
    } 
} 

和第二個例子:

public IEnumerable<Parent> GetParentsWhereChildHasThisValue(string childFiledValue) 
{ 
    Parent parent = null; 
    foreach (string line in MyCustomReader) 
    { 
     if (line.StartsWith("@")) 
     { 
      parent = Line.Create(line); 
     } 
     else //child 
     { 
      Child child = Child.Create(line); 
      if (child.FiledValue == childFiledValue) 
       yield return parent; 
     } 
    } 
} 

怎麼能使用LINQ來實現這兩個例子?

回答

5

這是不漂亮,但對於第一個像下面應該工作:

MyCustomReader.SkipWhile(line => line != uniqueParentName).Skip(1). 
            TakeWhile(line => !line.StartsWith("@")); 

編輯:好了,所以我很無聊。我認爲這會爲你做的第二個(即適合於LINQ但顯然它不是一個問題):

var res = MyCustomReader.Where(parentLine => parentLine.StartsWith("@")) 
     .Join(MyCustomReader.Where(childLine => !childLine.StartsWith("@")), 
       parentLine => parentLine, 
       childLine => MyCustomReader.Reverse<string>() 
        .SkipWhile(z => z != childLine) 
        .SkipWhile(x => !x.StartsWith("@")).First(), 
       (x, y) => new { Parent = x, Child = y }) 
     .Where(a => a.Child == childFiledValue).Select(a => a.Parent); 
+0

的將得到線,你可能需要添加。選擇(線=> Child.Create (線))到最後 – 2009-08-17 21:22:36

+0

它工作正常。謝謝 – Zoman 2009-08-17 21:31:58

+1

你可能需要找到第二個忍者:) – 2009-08-17 21:41:45