How to iterate slice starting from the last element

I need to iterate a slice from last element and ends with (n-2)th element circular_tuple_windows which needs ExactSizeIterator.
Is there a specific method implemented on slice which does exactly.
The output of the riter like method should be like this:

fn main() {
    let x = [1, 2, 3, 4].riter().copied();
    assert_eq!(x.next(), Some(4));
    assert_eq!(x.next(), Some(1));
    assert_eq!(x.next(), Some(2));
    assert_eq!(x.next(), Some(3));
    assert_eq!(x.next(), None);
}

You can use the rev() method to reverse the direction of iteration if the iterator supports it.

let items = [1, 2, 3, 4, 5];

for item in items.iter().rev() {
  println!("{}", item);
}

Will print out:

5
4
3
2
1

(playground)

But, I don't want it to be reversed. For me it should be like:

fn main() {
    let x = [1, 2, 3, 4].riter().copied();
    assert_eq!(x.next(), Some(4));
    assert_eq!(x.next(), Some(1));
    assert_eq!(x.next(), Some(2));
    assert_eq!(x.next(), Some(3));
    assert_eq!(x.next(), None);
}

There isn't, this really is a niche requirement. You could do it in a somewhat nicer way, e.g. in either of the following two ways:

let xs = [1, 2, 3, 4];
let mut x = xs.last().into_iter().chain(&xs[..xs.len() - 1]).copied();
let mut x = xs.iter().cycle().skip(xs.len() - 1).take(xs.len()).copied();

But, the problem is if I try to use the circular_tuple_windows from Itertools, it gives me this error.

   |
17 |                     a.last().into_iter().chain(&a[..a.len() - 1]).circular_tuple_windows().map(|(a, b, c)| a + b + c)
   |                                                                   ^^^^^^^^^^^^^^^^^^^^^^ the trait `ExactSizeIterator` is not implemented for `std::iter::Chain<std::option::IntoIter<&bool>, std::slice::Iter<'_, bool>>`

If you can change the slice, you can use the rotate_right() method:

fn main() {
    let mut x = [1, 2, 3, 4];
    x.rotate_right(1);
    let mut x = x.iter().copied();
    assert_eq!(x.next(), Some(4));
    assert_eq!(x.next(), Some(1));
    assert_eq!(x.next(), Some(2));
    assert_eq!(x.next(), Some(3));
    assert_eq!(x.next(), None);
}
2 Likes

I think its a good answer but, the problem is its immutable slice(&[T])

. So, you can't use rotate_left and rotate_right methods.

fn main() {
    let x = [1, 2, 3, 4];
    let (a, b) = x.split_at(x.len() -1);
    let iter = b.iter().copied().chain(a.iter().copied());
    assert_eq!(x.next(), Some(4));
    assert_eq!(x.next(), Some(1));
    assert_eq!(x.next(), Some(2));
    assert_eq!(x.next(), Some(3));
    assert_eq!(x.next(), None);
}

which it works also with circular_tuple_windows method(b.iter().copied().circular_tuple_windows().chain(a.iter().copied().circular_tuple_windows());

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.