Iterator: combine skip & take

For rust Iterator, both skip & take are

fn (self, ...)

so it consumes the current iterator.

I have a situation where I want to "split" on an iterator -- to COLLECT the first n items, then have an iterator that starts on the n+1th element.

Is there a 'functional' way to do this without manually writing a loop + mut accumulator?

I'd say you want Iterator::by_ref. Something like:

let mut it = vec![1, 2, 3].into_iter();
let v : Vec<_> = it.by_ref().take(2).collect();
println!("v = {:?}", v);
for x in it {
    println!("{}", x);
}
2 Likes

You may also look at https://docs.rs/itertools/0.8.0/itertools/trait.Itertools.html#method.next_tuple.

How would this work? From the docs, I'm reading:

Advances the iterator and returns the next items grouped in a tuple of a specific size (up to 4).

This tuple of size up to 4 seems very limiting.

Yes, tuple of size 4 is very limitting. The reason is probably lack of dependent types in Rust (aka const generics here), so you don't have any simple way of implementing something which is generic over tuple size. In this case it is just defined for every T which is implementing TupleCollect which I actually don't see in itertools (I don't have much time to go deep into this). I assume that TupleCollect is just defined for tuples of up to four elements, all of same type.

How would you use this to solve the originally asked question?

Altering zrk code:

let mut it = vec![1, 2, 3].into_iter();
let (x, y) = it.next_tuple(); // Or smthng like `let x: (_, _) = it.next_tuple();`
println!("v = {:?}", v);
println!("(x, y) = {:?}", (x, y);

You obviously need to know number of elements in compile time.