Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

iterator

rust

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.

like image 368
Nurbol Alpysbayev Avatar asked Nov 26 '19 07:11

Nurbol Alpysbayev


People also ask

How do you skip items in for loop?

You can use the continue statement if you need to skip the current iteration of a for or while loop and move onto the next iteration.

How do I skip loops in iterations?

If you want to skip a particular iteration, use continue . If you want to break out of the immediate loop, use break. If there are 2 loop, outer and inner.... and you want to break out of both the loop from the inner loop, use break with label (another question about label).

How do you skip multiple iterations in Python?

When you want to skip n values, call next() n+1 times (don't forget to assign the value of the last call to something) and then "call" continue.

How do you skip the first item in a for loop?

Use iter() and next() to skip first element of a for-loop User iter(object) to return an iterable for any iterable object . Call next(iterator) on iterator as the iterable for object to skip the first element of iterator .


Video Answer


2 Answers

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

like image 159
Jmb Avatar answered Oct 17 '22 14:10

Jmb


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()));
}
like image 3
Boiethios Avatar answered Oct 17 '22 12:10

Boiethios