Reputation: 123
I have a vector of some elements that I would like to iterate from some index and cycle around from the front again while only visiting each element a single time.
Ex. starting here at index 2,
[0, 1, 2, 3, 4, 5, 6]
^
I would like to have an iterator over the elements [2, 3, 4, 5, 6, 0, 1] (and avoid writing a loop everywhere I need to run through the vector this way). The standard iteration with cycle() + skip() seemed to be a good start, but it of cause never ends.
Is there any idiomatic way with rusts standard iterators?
Upvotes: 3
Views: 1581
Reputation: 154866
The obvious fix for your cycle/skip combo is to add a take()
to limit it:
fn cycle<T>(slice: &[T], start_pos: usize) -> impl Iterator<Item = &T> {
slice.iter().cycle().skip(start_pos).take(slice.len())
}
Another option is to just chain the two ranges, which even ends up a bit shorter:
fn cycle<T>(slice: &[T], start_pos: usize) -> impl Iterator<Item = &T> {
slice[start_pos..].iter().chain(&slice[..start_pos])
}
Both versions pass test such as:
let v = vec![0, 1, 2, 3, 4, 5, 6];
assert_eq!(cycle(&v, 2).copied().collect::<Vec<_>>(), vec![2, 3, 4, 5, 6, 0, 1]);
Upvotes: 3
Reputation: 181725
You can iterate over the two subslices, and use chain
to concatenate them together into a single iterator:
let v = vec![0, 1, 2, 3, 4, 5, 6];
let start_index = 2;
for e in v[start_index..].iter().chain(v[..start_index].iter()) {
println!("{}", e);
}
Upvotes: 3