How to skip n items from inside of a iterator loop?

て烟熏妆下的殇ゞ 提交于 2020-01-30 05:15:21

问题


This code:

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`
}

prints abcd, but I want to skip 2 chars if b was found, so that it prints ad. How do I do that?

I tried to put the iterator into a variable outside the loop and manipulate that iterator within the loop, but the Borrow Checker doesn't allow that.


回答1:


AFAIK you can't do that with a for loop. You will need to desugar it by hand:

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




回答2:


If you want to keep an iterator style, you can use std::iter::successors (I've replaced the special char with '!' for being more readable:

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()));
}


来源:https://stackoverflow.com/questions/59045408/how-to-skip-n-items-from-inside-of-a-iterator-loop

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!