Cycle a Rust iterator a given number of times - rust

How do I cycle through an iterator a finite number of times?
I would expect the output of something like this to be 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3 and then stop:
vec![1, 2, 3].iter().cycle(4)
// ^ but .cycle() doesn't take an argument...
I don't know the length of the iterator to begin with.

One simple way is to repeat the iterator itself, take the first 4 and flatten:
fn main() {
let v = vec![1, 2, 3];
let res = std::iter::repeat(v.iter())
.take(4)
.flatten()
.collect::<Vec<_>>();
dbg!(res);
}
Some micro-benchmark result using code in this gist comparing 3 different approaches:
repeat-take-flatten in this answer
hand-rolled loop
a cycle_n implementation mimicking Iterator::cycle.
Kudos to rustc, cycle_n consistently outperforms the other two when the input is reasonably large whereas repeat-take-flatten performs the best for small input.

There is no such an iterator in the std lib.
If you know the iterator size, you can take your number times the size of the iterator:
fn cycle_n_times<T: Clone>(slice: &[T], count: usize) -> impl Iterator<Item = &T> {
slice.iter().cycle().take(slice.len() * count)
}
Or you can write your own that is more general:
pub struct Ncycles<I> {
orig: I,
iter: I,
count: usize,
}
impl<I: Clone> Ncycles<I> {
fn new(iter: I, count: usize) -> Ncycles<I> {
Ncycles {
orig: iter.clone(),
iter,
count,
}
}
}
impl<I> Iterator for Ncycles<I>
where
I: Clone + Iterator,
{
type Item = <I as Iterator>::Item;
#[inline]
fn next(&mut self) -> Option<<I as Iterator>::Item> {
match self.iter.next() {
None if self.count == 0 => None,
None => {
self.iter = self.orig.clone();
self.count -= 1;
self.iter.next()
}
y => y,
}
}
}
#[test]
fn it_work() {
Ncycles::new(vec![1, 2, 3].iter(), 4).eq(&[1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]);
}

One could leverage slice::repeat, but I can't imagine this is very efficient:
let v = vec![1, 2, 3];
let it = v.iter();
println!("{:?}", it.map(|x| *x).collect::<Vec<i32>>().repeat(4).iter());

Related

How can I iterate over a sequence multiple times within a function?

I have a function that I would like to take an argument that can be looped over. However I would like to loop over it twice. I tried using the Iterator trait however I can only iterate over it once because it consumes the struct when iterating.
How should I make it so my function can loop twice? I know I could use values: Vec<usize> however I would like to make it generic over any object that is iterable.
Here's an example of what I would like to do: (Please ignore what the loops are actually doing. In my real code I can't condense the two loops into one.)
fn perform<'a, I>(values: I) -> usize
where
I: Iterator<Item = &'a usize>,
{
// Loop one: This works.
let sum = values.sum::<usize>();
// Loop two: This doesn't work due to `error[E0382]: use of moved value:
// `values``.
let max = values.max().unwrap();
sum * max
}
fn main() {
let v: Vec<usize> = vec![1, 2, 3, 4];
let result = perform(v.iter());
print!("Result: {}", result);
}
You can't iterate over the same iterator twice, because iterators are not guaranteed to be randomly accessible. For example, std::iter::from_fn produces an iterator that is most definitely not randomly accessible.
As #mousetail already mentioned, one way to get around this problem is to expect a Cloneable iterator:
fn perform<'a, I>(values: I) -> usize
where
I: Iterator<Item = &'a usize> + Clone,
{
// Loop one: This works.
let sum = values.clone().sum::<usize>();
// Loop two: This doesn't work due to `error[E0382]: use of moved value:
// `values``.
let max = values.max().unwrap();
sum * max
}
fn main() {
let v: Vec<usize> = vec![1, 2, 3, 4];
let result = perform(v.iter());
println!("Result: {}", result);
}
Result: 40
Although in your specific example, I'd compute both sum and max in the same iteration:
fn perform<'a, I>(values: I) -> usize
where
I: Iterator<Item = &'a usize>,
{
let (sum, max) = values.fold((0, usize::MIN), |(sum, max), &el| {
(sum + el, usize::max(max, el))
});
sum * max
}
fn main() {
let v: Vec<usize> = vec![1, 2, 3, 4];
let result = perform(v.iter());
println!("Result: {}", result);
}
Result: 40

How to perform element-wise subtraction between two vectors?

I have to Vecs: vec_a and vec_b. Both the same size. I want to perform element-wise subtraction between the two vectors and save the answer in a third vector vec_c. For example:
vec_a = [1, 2, 3]
vec_b = [0, 2, -3]
vec_c = vec_a - vec_b = [1, 0, 6]
The solution I've come with is this function:
pub fn elementwise_subtraction(vec_a: Vec<i32>, vec_b: Vec<i32>) -> Vec<i32> {
let mut vec_c = Vec::new();
for i in 0..vec_a.len() {
vec_c.push(vec_a[i] - vec_b[i]);
}
vec_c
}
I feel like this is a bit verbose for a pretty simple operation. Is there a better/more idiomatic way to do this?
There is no such thing built in, you have to implement it yourself or use a third-party crate.
Anyway, you can continue to improve your code using functional programming:
pub fn elementwise_subtraction(vec_a: Vec<i32>, vec_b: Vec<i32>) -> Vec<i32> {
vec_a.into_iter().zip(vec_b).map(|(a, b)| a - b).collect()
}
let vec_a = vec![1, 2, 3];
let vec_b = vec![0, 2, -3];
let vec_c = elementwise_subtraction(vec_a, vec_b);
assert_eq!(vec_c, [1, 0, 6])
If you want to make it more generic (e.g. accepting both slices or Vec, any subtractable type):
use std::ops::Sub;
pub fn elementwise_subtraction<N, IA, IB, F>(a: IA, b: IB) -> F
where
N: Sub,
IA: IntoIterator<Item = N>,
IB: IntoIterator<Item = N>,
F: FromIterator<N> + FromIterator<<N as Sub>::Output>,
{
a.into_iter().zip(b).map(|(a, b)| a - b).collect()
}
let vec_a = [1, 2, 3];
let vec_b = [0, 2, -3];
let vec_c: Vec<_> = elementwise_subtraction(vec_a, vec_b);
assert_eq!(vec_c, [1, 0, 6])
Try it on playground
You'll need to use zip and map:
fn main() {
let vec_a = [1, 2, 3];
let vec_b = [0, 2, -3];
let vec_c: Vec<i32> = vec_a
.iter()
.zip(vec_b)
.map(|(elem_a, elem_b)| elem_a - elem_b)
.collect();
for elem_c in vec_c {
println!("{}", elem_c);
}
}
Your method is likely the most efficient way since it uses straight indexing, but an iterator method could look like this:
assert_eq!(
vec_a
.iter()
.zip(vec_b)
.map(|(a, b)| a - b)
.collect::<Vec<_>>(),
vec![1, 0, 6]
);
"Better" is always subjective, so if performance is your priority you should benchmark different methods; I've been surprised by results before.

Insert into Rust array in place, push other elements down

I'm trying to do the following in Rust, specifically using arrays (I don't want to use vectors here, and want elements pushed out of the array if we're done).
let mut x = [1, 2, 3, 4, 5];
// array, number to insert, place to be inserted at
insert_in_place(&x, 7, 1);
// x is now [1, 7, 2, 3, 4];
How do you implement insert_in_place?
I think there's a way to do this using slices, but I'm still learning and wondering if there's a really elegant way to do this kind of thing.
fn insert_in_place<T>(array: &mut [T], value: T, index: usize) {
*array.last_mut().unwrap() = value;
array[index..].rotate_right(1);
}
Try it online!
Or equivalently:
fn insert_in_place<T>(array: &mut [T], value: T, index: usize) {
array[index..].rotate_right(1);
array[index] = value;
}
Try it online!
Iterate the slice, skipping elements before the index of the one you need to insert. Then swap each element with its previous element (or, for the first one, use the item to add).
fn insert_in_place<T>(x: &mut [T], new: T, index: usize) {
let mut next = new;
for e in x.iter_mut().skip(index) {
std::mem::swap(e, &mut next);
}
}
fn main() {
let mut x = [1, 2, 3, 4, 5];
// array, number to insert, place to be inserted at
insert_in_place(&mut x, 7, 1);
// x is now [1, 7, 2, 3, 4];
println!("{:?}", x);
}

How to idiomatically check if a 2-dimensional vector is a table? [duplicate]

Given a vector of vectors of some value T, ie. Vec<Vec<T>>.
What's the idiomatic way to check if the inner vectors have the same length? (without external dependencies)
That is, true if all the inner vectors have the same length, and false otherwise.
You can use the all method to check if all elements of an iterator match a predicate. Then just compare against the first element in the list.
fn main() {
let vec_of_vecs = vec![
vec![1, 2, 3],
vec![1, 2, 3],
vec![1, 2, 3],
vec![1, 2, 3],
vec![1, 2, 3],
vec![1, 2, 3, 4], // remove this to prove that it works for both cases
];
let all_same_length = vec_of_vecs
.iter()
.all(|ref v| v.len() == vec_of_vecs[0].len());
if all_same_length {
println!("They're all the same");
} else {
println!("They are not the same");
}
}
An other solution more generic and idiomatic in my opinion:
fn all_eq_len<'a, T, E: 'a>(collection: T) -> bool
where
T: IntoIterator<Item = &'a Vec<E>>,
{
let mut iter = collection.into_iter();
if let Some(first) = iter.next() {
let len = first.len();
iter.all(|v| v.len() == len)
} else {
true
}
}
And of course using itertools:
use itertools::Itertools;
vec_of_vecs.iter().map(|v| v.len()).all_equal()

Check if length of all vectors is the same in Rust

Given a vector of vectors of some value T, ie. Vec<Vec<T>>.
What's the idiomatic way to check if the inner vectors have the same length? (without external dependencies)
That is, true if all the inner vectors have the same length, and false otherwise.
You can use the all method to check if all elements of an iterator match a predicate. Then just compare against the first element in the list.
fn main() {
let vec_of_vecs = vec![
vec![1, 2, 3],
vec![1, 2, 3],
vec![1, 2, 3],
vec![1, 2, 3],
vec![1, 2, 3],
vec![1, 2, 3, 4], // remove this to prove that it works for both cases
];
let all_same_length = vec_of_vecs
.iter()
.all(|ref v| v.len() == vec_of_vecs[0].len());
if all_same_length {
println!("They're all the same");
} else {
println!("They are not the same");
}
}
An other solution more generic and idiomatic in my opinion:
fn all_eq_len<'a, T, E: 'a>(collection: T) -> bool
where
T: IntoIterator<Item = &'a Vec<E>>,
{
let mut iter = collection.into_iter();
if let Some(first) = iter.next() {
let len = first.len();
iter.all(|v| v.len() == len)
} else {
true
}
}
And of course using itertools:
use itertools::Itertools;
vec_of_vecs.iter().map(|v| v.len()).all_equal()

Resources