如何将ReadLine循环重构为Linq

Los*_*nos 3 c# linq

我想使下面的代码更清洁(在旁观者的眼中).

var lines = new StringReader(lotsOfIncomingLinesWithNewLineCharacters);
var resultingLines = new List<string>();

string line;
while( (line = lines.ReadLine() ) != null )
{
    if( line.Substring(0,5) == "value" )
    {
        resultingLines.Add(line);
    }
}
Run Code Online (Sandbox Code Playgroud)

喜欢的东西

var resultingLinesQuery = 
    lotsOfIncomingLinesWithNewLineCharacters
    .Where(s=>s.Substring(0,5) == "value );
Run Code Online (Sandbox Code Playgroud)

希望我已经说明我不希望将结果作为列表(不填充内存)并且StringReader不是必需的.

有一个天真的解决方案来创建扩展并在那里移动ReadLine但我感觉可能有更好的方法.

Jon*_*eet 11

基本上你需要一种从a中提取线条的方法TextReader.这是一个只需迭代一次的简单解决方案:

public static IEnumerable<string> ReadLines(this TextReader reader)
{
    string line;
    while ((line = reader.ReadLine()) != null)
    {
        yield return line;
    }
}
Run Code Online (Sandbox Code Playgroud)

您可以使用:

var resultingLinesQuery = 
    new StringReader(lotsOfIncomingLinesWithNewLineCharacters)
    .ReadLines()
    .Where(s => s.Substring(0,5) == "value");
Run Code Online (Sandbox Code Playgroud)

但理想情况下,您应该能够IEnumerable<T>多次迭代.如果你只需要这个字符串,你可以使用:

public static IEnumerable<string> SplitIntoLines(this string text)
{
    using (var reader = new StringReader(text))
    {
        string line;
        while ((line = reader.ReadLine()) != null)
        {
            yield return line;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后:

var resultingLinesQuery = 
    lotsOfIncomingLinesWithNewLineCharacters
    .SplitIntoLines()
    .Where(s => s.Substring(0,5) == "value");
Run Code Online (Sandbox Code Playgroud)

  • @FelipeOriani:它将懒惰地迭代 - 所以除非你调用`ToList()`或类似的东西,否则你永远不会在内存中拥有完整的集合. (5认同)