How to chain arbitrary number of filters to iterator

Tried some stuff with iterators and get the following error and frankly I don't understand what exactly is the problem here

Please run cargo check and paste the output here in a text block:
```
output here
```
(The output may also be more helpful to you directly than whatever your editor is providing.)

1 Like

For the single filter try let iter = iter.filter(...);

For the commented out thing with a loop, perhaps the best approach would be a single filter that loops over the collection of filters and checks if all succeed.

the code

#[derive(Clone, Copy, Debug)]
struct Item {

}

fn filter(colection : &[Item], filters : &[i32]) -> Vec<Item> {
    let iter = colection.iter().map(|s| *s).into_iter().filter(|_item| true);

    iter.filter(|item| true);
    // for filter in filters.iter() {
    //     iter = iter.filter::<Item>(|item| true);
    // }

    iter.collect::<Vec<Item>>()
}


fn main() {
    println!("Hello, world!");
}

The cargo check output

cargo check                                                                                                                                                                    101 ✘ 
    Checking tests v0.1.0 (/home/kalin/Projects/rust_tests/tests)
warning: unused variable: `item`
  --> src/main.rs:10:18
   |
10 |     iter.filter(|item| true);
   |                  ^^^^ help: if this is intentional, prefix it with an underscore: `_item`
   |
   = note: `#[warn(unused_variables)]` on by default

warning: unused variable: `filters`
 --> src/main.rs:7:32
  |
7 | fn filter(colection : &[Item], filters : &[i32]) -> Vec<Item> {
  |                                ^^^^^^^ help: if this is intentional, prefix it with an underscore: `_filters`

error[E0382]: use of moved value: `iter`
   --> src/main.rs:15:5
    |
8   |     let iter = colection.iter().map(|s| *s).into_iter().filter(|_item| true);
    |         ---- move occurs because `iter` has type `Filter<Map<std::slice::Iter<'_, Item>, [closure@src/main.rs:8:37: 8:43]>, [closure@src/main.rs:8:64: 8:76]>`, which does not implement the `Copy` trait
9   | 
10  |     iter.filter(|item| true);
    |          ------------------- `iter` moved due to this method call
...
15  |     iter.collect::<Vec<Item>>()
    |     ^^^^ value used here after move
    |
note: this function takes ownership of the receiver `self`, which moves `iter`
   --> /home/kalin/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/iter/traits/iterator.rs:802:18
    |
802 |     fn filter<P>(self, predicate: P) -> Filter<Self, P>
    |                  ^^^^

For more information about this error, try `rustc --explain E0382`.
warning: `tests` (bin "tests") generated 2 warnings
error: could not compile `tests` due to previous error; 2 warnings emitted
    ~/Projects/rust_tests/tests    master ?4       

It obviously want me to chain those Combinators one after another with dot operator but I don't understand why and is it possible to find workaround for that

Never mind. I'm just dumb. This work

fn filter(colection : &[Item], filters : &[i32]) -> Vec<Item> {
    let iter = colection.iter().map(|s| *s).into_iter().filter(|_item| true);

    let iter = iter.filter(|item| true);
    // for filter in filters.iter() {
    //     let iter = iter.filter::<Item>(|mut item| true);
    // }

    iter.collect::<Vec<Item>>()
}
2 Likes

Look like the second part in the comment is impossible. Every combinator in the chain return different type. That prevent to use this type of logic in loop

You can with boxed iterators:

let mut iter: Box<dyn Iterator<Item = Item>> = Box::new(iter.filter(|item| true));
for filter in filters.iter() {
    iter = Box::new(iter.filter(|mut item| true));
}

However it's inefficient.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.