【问题标题】:How to skip multiple iterations in a while loop如何在while循环中跳过多次迭代
【发布时间】:2014-10-30 17:47:32
【问题描述】:

我在 While 循环中逐行读取文本文件。当我到达特定行时,我想跳过当前和接下来的 3 次迭代。

我想我可以使用计数器之类的东西来做到这一点。但我想知道是否有更优雅的方式?

using (var sr = new StreamReader(source))
{
    string line;
    while ((line = sr.ReadLine()) != null)
    {
        if (line == "Section 1-1")
        {
            // skip the next 3 iterations (lines)
        }
    }
}

【问题讨论】:

  • 在 if 子句中简单地执行 ReadLines 3 次,每次检查是否为空
  • @HugoRune 谢谢,这就是我所说的优雅。
  • 再读 3 行,但不要使用这些行

标签: c# while-loop streamreader continue


【解决方案1】:

让自己成为一个丢弃给定行数的函数 (DiscardLines) 并使用它:

string line;
while ((line = sr.ReadLine()) != null)
{
    if (line == "Section 1-1")
    {
        DiscardLines(sr, 3);
    }
}

这使主循环非常简单。计数器现在隐藏在 DiscardLines 中。

【讨论】:

    【解决方案2】:

    有一个for 循环执行sr.ReadLine 3 次并丢弃结果,如:

    using (var sr = new StreamReader(source))
    {
        string line;
        while ((line = sr.ReadLine()) != null)
        {
            if (line == "Section 1-1")
            {
                for (int i = 0; i < 3; i++)
                {
                    sr.ReadLine();
                }
            }
        }
    }
    

    您应该检查sr.ReadLine 返回null 或者流是否已经结束。

    【讨论】:

    • 感谢 Habib,这是我一直在寻找的简单而优雅的答案。我想我不需要检查null
    【解决方案3】:
    using (var sr = new StreamReader(source))
    {
        string line;
        int linesToSkip = 0;
        while ((line = sr.ReadLine()) != null)
        {
            if (linesToSkip > 0)
            {
                linesToSkip -= 1;
                continue;
            }
            if (line == "Section 1-1")
            {
                // skip the next 3 iterations (lines)
                linesToSkip = 3;
            }  
        }
    }
    

    【讨论】:

    • 感谢 Zer0 的回答,我 +1 你,但正如我在问题中所说,我试图避免 counter
    【解决方案4】:

    您可以将File.ReadAllLines 与方法扩展一起使用:

    public static IEnumerable<string> SkipLines(string file, string line, int count)
    {
        var enumerable = File.ReadLines(file).GetEnumerator();
        while (enumerable.MoveNext())
        {
            var currentLine = enumerable.Current;
            if (currentLine == line)
            {
                var currentCount = 0;
                while(enumerable.MoveNext() && currentCount < count) 
                {
                      currentCount += 1;
                }
            }
    
            yield return currentLine;
        }
    }
    

    用法:

    foreach (var line in SkipLines(source, "Section 1-1", 3))
    {
       // your line
    }
    

    请记住:ReadLines 是惰性的 - 并非所有行都一次加载到内存中。

    【讨论】:

    • 谢谢 pwas,这比ReadLine() 快吗?我的文本文件有点大。大约 100,000 行。
    • 你从哪里得到MoveNext?我在string[] 下看不到它。
    • @gunr2171 谢谢!我输入了错误的方法名称 - 它是 ReadLines 而不是 ReadAllLines :) +1 给你。
    • MoveNext 也不属于 IEnumerable(至少公开)。
    • Keep in mind: ReadAllLines is lazy 不,不是。 ReadLines 是懒惰的,ReadAllLines 读取所有行。
    猜你喜欢
    • 2019-05-06
    • 2013-01-29
    • 2016-10-22
    • 2023-04-07
    • 2015-02-07
    • 2013-07-24
    • 2019-05-23
    • 1970-01-01
    相关资源
    最近更新 更多