2009-08-17 30 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