Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to iterate over two elements in a collection stepping by one using Iterator?

Tags:

iterator

rust

Suppose we have a vector:

let a = vec![1, 2, 3];

What is the best and shortest way to iterate over the elements so, that in the first iteration I receive a tuple of (1, 2), and in the next iteration - (2, 3), until there are no elements, so without producing the (3, None) or anything like that? It seems that a.chunks(2) is a bit different, it steps by two, while I need to step by one over every two consecutive elements in a collection.

like image 303
Victor Polevoy Avatar asked Sep 07 '25 00:09

Victor Polevoy


2 Answers

There are multiple ways to do so:

Using the standard library:

.zip

let result = a.iter()
    .zip(a.iter().skip(1))
    .inspect(|(a, b)| println!("a: {}, b: {}", a, b))
    .collect::<Vec<_>>();

.windows

let result = a.windows(2)
    .inspect(|w| println!("a: {}, b: {}", w[0], w[1]))
    .collect::<Vec<_>>();

Worth noting, in case this matters, is that windows() iterates over subslices, so unlike the above method, collect() in this case will not give you a Vec of tuples.

Using the Itertools crate:

.tuple_windows

use itertools::Itertools;

let result = a.iter()
    .tuple_windows()
    .inspect(|(a, b)| println!("a: {}, b: {}", a, b))
    .collect::<Vec<_>>();

All of the above methods will print the following:

a: 1, b: 2
a: 2, b: 3

As a bonus, Itertools as of recent also has a .circular_tuple_windows(), which performs an extra iteration by including the last (3) and first (1) element:

use itertools::Itertools;

let result = a.iter()
    .circular_tuple_windows()
    .inspect(|(a, b)| println!("a: {}, b: {}", a, b))
    .collect::<Vec<_>>();
a: 1, b: 2
a: 2, b: 3
a: 3, b: 1
like image 176
Jason Avatar answered Sep 10 '25 05:09

Jason


You can also use chunks(). Now the elements will not overlap.

fn main() {
    let vec = vec![1, 2, 4, 5, 8, 9];
    let new_thing = vec.chunks(2).map(|x| println!("{} and {}", x[0],
    x[1])).collect::<Vec<_>>();
}
1 and 2
4 and 5
8 and 9
like image 30
Daan van der Plas Avatar answered Sep 10 '25 04:09

Daan van der Plas