Pierre-olivier Gendraud
Pierre-olivier Gendraud

Reputation: 1927

Is it possible to concatenate iterators?

let vec = iter::repeat("don't satisfy condition 1") // iterator such as next() always "don't " satisfy condition 1"
    .take_while(|_| {
        satisfycondition1.satisfy() // true is condition 1 is satisfied else false
    })
    .collect();

This code creates a vector of n elements with n equal to the number of times condition 1 is not respected.

I would like now to create a vector of n + m elements with n equal to the number of times that condition 1 is not respected and m the number of times that condition 2 is not respected.

The code should look like something like this:

let vec = iter::repeat("dont't satisfy condition 1")
    .take_while(|_| {
        satisfycondition1.satisfy() 
    })
    .union(
        iter::repeat("has satisfed condition 1 but not 2 yet")
        .take_while(|_| {
            satisfycondition2.satisfy() 
        })
    )
    .collect();

I know I could create two vectors and then concatenate them but it's less efficient.

You can use this code to understand what does repeat:

use  std::iter;

fn main() {
    let mut c = 0;
    let z: Vec<_> = iter::repeat("dont't satisfy condition 1")
        .take_while(|_| {
            c = c + 1;
            let rep = if c < 5 { true } else { false };
            rep
        })
        .collect();
    println!("------{:?}", z);
}

Upvotes: 30

Views: 28048

Answers (1)

SCappella
SCappella

Reputation: 10474

It seems like std::iter::chain is what you're looking for.

use std::iter;

fn main() {
    let mut c = 0;
    let mut d = 5;
    let z: Vec<_> = iter::repeat("don't satisfy condition 1")
        .take_while(|_| {
            c = c + 1;
            let rep = if c < 5 { true } else { false };
            rep
            // this block can be simplified to
            // c += 1;
            // c < 5
            // Clippy warns about this
        })
        .chain(
            iter::repeat("satisfy condition 1 but not 2").take_while(|_| {
                d -= 1;
                d > 2
            }),
        )
        .collect();
    println!("------{:?}", z);
}

(playground link)

I can't comment on the semantics of your code, though. If you're trying to see which elements of an iterator "satisfy condition 1 but not 2", this wouldn't be how you do it. You would use std::iter::filter twice (once with condition 1 and once with not condition 2) to achieve that.

Upvotes: 48

Related Questions