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