如何存储迭代器或对象的异构列表,这些列表可以转换为可以多次使用的迭代器?

问题描述

是否存在一种很好的方法来存储迭代器或对象的异构列表,这些列表可以转换为可以多次使用的迭代器?在一种情况下,我想以多种方式遍历向量。通常,这些索引来自某个范围或另一个向量,但这不是保证。另外,这些索引将被多次使用,因此它们必须是可重用的。有一个好的方法可以做到这一点吗?作为一种尝试,我们有以下代码

// Create a struct to hold a list of items that generate indices and a vector
struct Foo {
    data: Vec<f64>,index_list: Vec<Box<dyn Iterator<Item = usize>>>,}

// Function that iterates over elements in the data
fn bar(f: &mut Foo) {
    for indices in &mut f.index_list {
        println!("Start of iteration");
        for i in indices {
            println!("{}",f.data[i])
        }
    }
}

// Test the routine
fn main() {
    let mut f = Foo {
        data: vec![0.1,1.2,2.3,3.4],index_list: vec![
            Box::new((0..=1).into_iter()),Box::new(vec![2,1,3].into_iter()),],};

    // Want these two functions to not consume the iterators and produce the
    // same result
    bar(&mut f);
    bar(&mut f);
}

这产生

Start of iteration
0.1
1.2
Start of iteration
2.3
1.2
3.4
Start of iteration
Start of iteration

这应该是预期的。 Foo结构中的迭代器在第一次调用时间条时被消耗。我想以不变的方式将f传递给foo,以便多次调用foo将返回相同的结果。我也强烈不希望将索引收集到向量中,因为实际用例将涉及非常长的索引列表。因此,此示例中不一定存在内存限制。

无论如何,删除上面的可变性会导致编译器错误

error[E0277]: `&Box<dyn Iterator<Item = usize>>` is not an iterator
  --> src/main.rs:14:18
   |
14 |         for i in indices {
   |                  ^^^^^^^ `&Box<dyn Iterator<Item = usize>>` is not an iterator
   |
   = help: the trait `Iterator` is not implemented for `&Box<dyn Iterator<Item = usize>>`
   = note: `Iterator` is implemented for `&mut std::Boxed::Box<dyn std::iter::Iterator<Item = usize>>`,but not for `&std::Boxed::Box<dyn std::iter::Iterator<Item = usize>>`
   = note: required because of the requirements on the impl of `IntoIterator` for `&Box<dyn Iterator<Item = usize>>`
   = note: required by `into_iter`

error: aborting due to prevIoUs error

For more information about this error,try `rustc --explain E0277`.

尝试克隆索引会给出:

error[E0277]: `&Box<dyn Iterator<Item = usize>>` is not an iterator
  --> src/main.rs:14:18
   |
14 |         for i in indices.clone() {
   |                  ^^^^^^^^^^^^^^^ `&Box<dyn Iterator<Item = usize>>` is not an iterator
   |
   = help: the trait `Iterator` is not implemented for `&Box<dyn Iterator<Item = usize>>`
   = note: `Iterator` is implemented for `&mut std::Boxed::Box<dyn std::iter::Iterator<Item = usize>>`,but not for `&std::Boxed::Box<dyn std::iter::Iterator<Item = usize>>`
   = note: required because of the requirements on the impl of `IntoIterator` for `&Box<dyn Iterator<Item = usize>>`
   = note: required by `into_iter`

error: aborting due to prevIoUs error

并尝试在cloned上使用index_list会给出:

error[E0277]: the trait bound `dyn Iterator<Item = usize>: Clone` is not satisfied
  --> src/main.rs:12:40
   |
12 |     for indices in f.index_list.iter().cloned() {
   |                                        ^^^^^^ the trait `Clone` is not implemented for `dyn Iterator<Item = usize>`
   |
   = note: required because of the requirements on the impl of `Clone` for `Box<dyn Iterator<Item = usize>>`

error[E0277]: the trait bound `dyn Iterator<Item = usize>: Clone` is not satisfied
  --> src/main.rs:12:20
   |
12 |     for indices in f.index_list.iter().cloned() {
   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `dyn Iterator<Item = usize>`
   |
   = note: required because of the requirements on the impl of `Clone` for `Box<dyn Iterator<Item = usize>>`
   = note: required because of the requirements on the impl of `Iterator` for `Cloned<std::slice::Iter<'_,Box<dyn Iterator<Item = usize>>>>`
   = note: required because of the requirements on the impl of `IntoIterator` for `Cloned<std::slice::Iter<'_,Box<dyn Iterator<Item = usize>>>>`
   = note: required by `into_iter`

error: aborting due to 2 prevIoUs errors

解决方法

您可以存储返回这些迭代器的函数列表:

struct Foo<'a> {
    data: Vec<f64>,index_list: Vec<&'a dyn Fn() -> Box<dyn Iterator<Item = usize>>>,}

fn bar(f: &mut Foo) {
    for indices in &mut f.index_list {
        println!("Start of iteration");
        for i in indices() {
            println!("{}",f.data[i])
        }
    }
}

fn main() {
    let mut f = Foo {
        data: vec![0.1,1.2,2.3,3.4],index_list: vec![
            &|| Box::new((0..=1).into_iter()),&|| Box::new(vec![2,1,3].into_iter()),],};

    bar(&mut f);
    bar(&mut f);
}