【问题标题】:How to skip n items from inside of an iterator loop?如何从迭代器循环内部跳过 n 个项目?
【发布时间】:2020-03-21 13:06:29
【问题描述】:

这段代码:

play

fn main() {
    let text = "abcd";

    for char in text.chars() {
        if char == 'b' {
            // skip 2 chars
        }
        print!("{}", char);
    }
    // prints `abcd`, but I want `ad`
}

打印abcd,但如果找到b,我想跳过2个字符,以便打印ad。我怎么做?

我试图将迭代器放入循环外的变量中并在循环内操作该迭代器,但借用检查器不允许这样做。

【问题讨论】:

    标签: rust iterator


    【解决方案1】:

    AFAIK 你不能用for 循环来做到这一点。您需要手动脱糖:

    let mut it = text.chars();
    while let Some(char) = it.next() {
        if char == 'b' {
            it.nth(1); // nth(1) skips/consumes exactly 2 items
            continue;
        }
        print!("{}", char);
    }
    

    Playground

    【讨论】:

    • 如果我想跳过,比如 50 个字符怎么办?调用.next 50 次既不好也不快。我尝试通过将第二个 .next 替换为 .skip 来修改您的示例,但这不起作用。
    • 我的错!你的答案(几乎)是正确的!我对其进行了轻微编辑,以便更好地匹配我的情况。
    • 请记住,“调用 50 次”仅适用于人,尤其是当我们谈论迭代器 api 时,它是高度可优化的,LLVM 可以轻松地分解此类重复性任务。除非您自己生成并查看 ASM,否则您不能真正声称它发生了“50 次”,您的 cpu 会以任何一种方式递增检查 50 次,调用很可能会被忽略。
    • 你链接的内容完全不同,所以它绝不会让我错,你从头开始迭代 N 次,我在同一个迭代器上谈论 iter().next(),此外,如果您正在手动编写解析器,无论如何您可能都应该手动使用.next(),所以它完全解决了这个问题。
    • @NurbolAlpysbayev 如果您忘记更新游乐场链接,请避免未经许可更改代码 - -
    【解决方案2】:

    如果你想保持迭代器风格,你可以使用std::iter::successors(为了更易读,我已经用'!'替换了特殊字符:

    fn my_iter<'a>(s: &'a str) -> impl Iterator<Item = char> + 'a {
        let mut it = s.chars();
    
        std::iter::successors(it.next(), move |c| {
            if *c == '!' {
                it.next().and_then(|_| it.next())
            } else {
                it.next()
            }
        })
        .filter(|c| *c != '!')
    }
    
    fn main() {
        assert!(my_iter("a!bc").eq("ac".chars()));
        assert!(my_iter("!abcd").eq("bcd".chars()));
        assert!(my_iter("abc!d").eq("abc".chars()));
        assert!(my_iter("abcd!").eq("abcd".chars()));
    }
    

    【讨论】:

    • 非常有趣!但是我个人觉得它的可读性较差(是的,我的大脑是程序性的,而不是功能性的)
    • 这不适用于! 的两个连续序列,为什么要过滤?
    • @Stargateur 尝试删除它...
    • from_fn 更有意义:play.rust-lang.org/…
    • @Stargateur 你最好这样写:play.rust-lang.org/…
    猜你喜欢
    • 2019-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-23
    相关资源
    最近更新 更多