如何从 for 循环中的迭代器中获取多个值?

How can I take a number of values from an iterator inside a for loop?

我有一个无限迭代器,我想从迭代器打印不同的切片。

所以,如果我调用 extract(8,&[1,2,3,4]),我想在控制台中 see/get:

1
2 3
4 1 2
3 4 1 2
3 4 1 2 3
4 1 2 3 4 1
2 3 4 1 2 3 4

我的尝试:

fn extract(n: usize, seq: &[u16]) {
    let mut iterator = seq.iter().cycle();

    for it in 1..n {
        iterator.take(it).for_each(|x| print!("{} ", x)); // <- Problem is here
        print!("\n");
    }
}

当我编译时:

warning: variable does not need to be mutable
 --> src/lib.rs:2:9
  |
2 |     let mut iterator = seq.iter().cycle();
  |         ----^^^^^^^^
  |         |
  |         help: remove this `mut`
  |
  = note: `#[warn(unused_mut)]` on by default

error[E0382]: use of moved value: `iterator`
 --> src/lib.rs:5:9
  |
2 |     let mut iterator = seq.iter().cycle();
  |         ------------ move occurs because `iterator` has type `std::iter::Cycle<std::slice::Iter<'_, u16>>`, which does not implement the `Copy` trait
...
5 |         iterator.take(it).for_each(|x| println!("{} ", x));
  |         ^^^^^^^^ value moved here, in previous iteration of loop

我知道迭代器在每次循环迭代中都会改变它的值。这就是为什么我标记为变异变量。但是不知何故, iterator var 被用作函数的参数(我看不到)并且迭代器被移动了。所以在下一个循环迭代中,iterator var 超出了范围,我得到了移动值错误。

为了更好地理解我的代码:

如果您查看确切的错误消息:

error[E0382]: use of moved value: `iterator`
 --> src/lib.rs:5:6
  |
2 |   let mut iterator = seq.iter().cycle();
  |       ------------ move occurs because `iterator` has type `std::iter::Cycle<std::slice::Iter<'_, u16>>`, which does not implement the `Copy` trait
...
5 |      iterator.take(it).for_each(|x| println!("{} ", x)); // <- Problem is here
  |      ^^^^^^^^ value moved here, in previous iteration of loop

编译器在值被移动的位置下划线,即在iterator.take(…)中。我们来看看Iterator::take的定义:

fn take(self, n: usize) -> Take<Self>

它需要self ,也就是说,要调用它,你必须移动实例。

正如其他人所写,take 消耗了您的迭代器。为避免这种情况,您可以使用 by_ref 包装原始迭代器并且可以在不消耗原始迭代器的情况下使用

fn extract(n: usize, seq: &[u16]) {
    let mut iterator = seq.iter().cycle();

    for it in 1..n {
        iterator.by_ref().take(it).for_each(|x| println!("{} ", x));
        print!("\n");
    }
}