Inclusive take_while and split

I have a use case where I want to take elements from an iterator until a certain condition.
The take_while function seemed to be made for that, however it removes an element!
While looking for a better solution, I noticed that with a slice, the split function would have the same "problem". (It's only a problem in my use case)

In this simple example, i want to split the iterator or slice into [1,2,3] and [4,5]:

let v = [1,2,3,4,5];
let mut it = v.iter();
it.by_ref().take_while(|&&a|a<3); // 1, 2
it; // 4, 5
v.split(|&a|a==3); //[1,2], [4,5]

But the 3 is removed.
How should I do this instead? Is there some function I'm missing?
I know I can just use a while loop and some mutable state, but I would like a clean solution.

The itertools crate has two methods peeking_take_while and taking_while_ref for this, depending on how you want the element to be restored:

use itertools::Itertools;

fn main() {
    let mut it = [1, 2, 3, 4, 5].iter();
    println!("{}", it.peeking_take_while(|&x| *x < 3).format(", "));
    println!("{}", it.take_while_ref(|&x| *x < 5).format(", "));
    println!("{}", it.format(", "));



1, 2
3, 4

There is a nightly method split_inclusive that does what you want.

Alternatively, you can manually iterate using the methods available on stable:

fn main() {
    let mut slice: &[_] = &[1, 2, 3, 4, 5];

    while let Some(index) = slice.iter().position(|x| *x % 2 == 0) {
        let (piece, rest) = slice.split_at(index + 1);
        println!("{:?}", piece);
        slice = rest;

    println!("Remaining: {:?}", slice);



[1, 2]
[3, 4]
Remaining: [5]

Thank you very much!
Including itertools and nightly, there are so many of these iterator functions!
It is so easy to overlook the ones you need, at least for me :wink:

1 Like