I have an iterator that I would like to analyze using a sliding window of size w
. I try to move the first w
items from the iterator into a data structure and would like iterate through the remaining items. However, when I use numbers.take(w)
I lose ownership of the iterator and cannot consume the remaining items:
use std::collections::VecDeque;
pub fn analysis<I>(numbers: I, w: usize)
where
I: Iterator<Item = u64>,
{
let mut window = VecDeque::with_capacity(w);
for number in numbers.take(w) {
window.push_back(number);
}
for (i, number) in numbers.enumerate() {
// do some analysis
}
}
error[E0382]: use of moved value: `numbers`
--> src/main.rs:12:24
|
8 | for number in numbers.take(w) {
| ------- value moved here
...
12 | for (i, number) in numbers.enumerate() {
| ^^^^^^^ value used here after move
|
= note: move occurs because `numbers` has type `I`, which does not implement the `Copy` trait
I found a workaround using the tee
function from the itertools
crate:
extern crate itertools;
use itertools::Itertools;
use std::collections::VecDeque;
pub fn analysis<I>(numbers: I, w: usize)
where
I: Iterator<Item = u64>,
{
let mut window = VecDeque::with_capacity(w);
let (first_numbers, numbers) = numbers.tee();
for number in first_numbers.take(w) {
window.push_back(number);
}
for number in numbers.skip(w) {
window.pop_front();
window.push_back(number);
// do stuff
}
}
However, this strikes me as a little unwieldy. Is there a way to solve this without cloning or duplicating the iterator? In other words: is there a way to split an iterator into two segments that can be used independently?