Compare a Vec with a Range in rust - rust

I want to check if a Vec is equal to [0, 1, 2, ...]. I've tried various variants of:
vec == &(0..vec.len())
But none of them seem to work. Do I just have to write a loop out long-hand?

You can use iterators to compare a Vec<T> (or more generally, a slice [T]) to a range (Playground):
let v = vec![0, 1, 2, 3, 4];
if v.iter().cloned().eq(0..v.len()) {
println!("v contains 0..5");
} else {
println!("v doesn't contain 0..5");
}
Let's dissect the important part:
v.iter().cloned().eq(0..v.len())
v.iter() creates an iterator over references to the elements in the vector (Iterator<Item = &{integer}>).
.cloned() clones each element in the iterator to go from reference to owned value. This is required because we cannot compare &{integer} to {integer}. Luckily, cloning a simple integer is basically free. So now we have Iterator<Item = {integer}>.
.eq is a method of Iterator which compares the iterator to another iterator.
0..v.len() is an range from 0 (inclusive) to v.len() (exclusive). Such a range implements Iterator.

Related

vec!() dereferencing when iterating with explicit type

let numbers = vec![1, 2, 3, 4, 5, 6, 7, 8, 9];
let even_numbers: Vec<i32> = numbers.iter().filter(|&n| n % 2 == 0).map(|n| *n).collect();
let even_numbers: Vec<_> = numbers.iter().filter(|&n| n % 2 == 0).map(|n| n).collect();
When the type is explicit I have to dereference n but if I don't state the type the compiler seems to know and automatically picks the value. Am I missing something, should it not be the other way around?
Why do I have to dereference with the explicit type but don't need to with _?
.iter() produces an iterator with an element type of &i32.
To collect into a Vec<i32>, you have to reference to copy the actual integer from the reference. That's what .map(|n| *n) does. (BTW .copied() exists for this purpose).
The Vec<_> tells the compiler "I just want a vector, but infer the element type" so it does just that and picks the element type from the iterator: &i32.
You can instead use .into_iter() on the original Vec, which will consume the vector and return an iterator of owned (not references) elements (i32) directly.

How to compare the value of next element with the current element in an iterator without a loop and for_each?

I have a vector like [1, 2, 4, 3], I want to remove 3 because 3 is smaller than 4.
I want to use the iterator to solve this problem, and do not use the loop or for_each.
The first step I think need to do is vec.into_iter, but I don't know what to do next.
To reformulate, you want to remove any element smaller than the previous element.
Let's write a function to do so. As you want to work exclusively with iterators, therefore in a functional style, we are going to assume the input vector is immutable, so the function should take a slice as input, and return a new Vec:
fn remove_smaller<T: Ord + Copy>(v: &[T]) -> Vec<T> {
v.iter()
.rev()
.collect::<Vec<_>>()
.windows(2)
.filter(|a| a[0] > a[1])
.map(|a| *a[0])
.chain([v[0]])
.rev()
.collect()
}
Let's explain what this function is doing, using vec![1, 2, 4, 3] as sample input.
We first reverse the order of the vector so we can operate on windows looking at the previous value, and collect it into a new vector (needed as windows is implemented for slices only).
&[3, 4, 2, 1]
windows(2) returns an iterator that will yield overlapping pairs of elements of the slice, except the last element, which has no next:
&[3, 4], &[4, 2], &[2, 1]
We then filter with filter(|a| a[0] > a[1]) meaning we only keep entries which are ordered (hence why type of input needs to be Ord):
&[4, 2], &[2, 1]
We then map with map(|a| *a[0]) in order to keep each value, which needs T to be Copy:
4, 2
Now, since we are missing the first element of the input array, we need to add it again, using .chain([v[0]]) giving us:
4, 2, 1
We then reverse the iterator to obtain the output array in correct order:
1, 2, 4
See it in action in the playground.
This is not a very efficient method to achieve the result, as it needs to allocate twice as much memory as the input.
You can use the zip and skip functionality to put together two elements of an array.
Following the footsteps of #sirdarius, Here is how your function can be:
fn remove_smaller<T: Ord + Copy>(v: &[T]) -> Vec<T> {
let mut res = vec![v[0]];
res.extend(
v.iter()
.zip(v.iter().skip(1))
.filter(|(a, b)| a < b)
.map(|(_, b)| *b),
);
res
}
Walk through:
We fist create our result vector and push the first element in it since it is always in the answer vector.
Then we extend our result vector by another iterator which would perform the following:
create a tuple for each element of the array with indices of the same array but one index ahead (v.iter().skip(1)).
we then filter out pairs which meet our ordering and finally, we map the pair to a single value.
There is an iterator only way to do what you wanted in O(1) space.
fn non_decreasing(v: Vec<i32>) -> Vec<i32> {
if v.is_empty() {
return v;
}
let first = v[0];
once(first)
.chain(
v.into_iter()
.skip(1)
.scan(first, |last_max, cur_elem| {
if cur_elem < *last_max {
Some(None)
} else {
*last_max = cur_elem;
Some(Some(cur_elem))
}
})
.flatten(),
)
.collect()
}
This function will not use any extra space (even for the output, on newer rustc versions). It will return a vector that's non-decreasing. That is, each element in the result vector will be >= the previous one.
If you wanted to compare the elements only to the previous element and not the previous largest, then just add the *last_max = cur_elem line to the if branch as well.

How to repeat each element of iterator n times?

I am currently learning Rust, and I stumbled upon an operation for which I can find neither a standard implementation in std nor a reasonably formed snippet of code, which would do what I would like it to do.
Basically I would like to repeat each element of an iterator a given number of times. So for example if a had an iterator of [1,2,3], then by repeating each element 3 times for example I mean that output should be [1,1,1,2,2,2,3,3,3].
How would one do it idiomatically in Rust?
You can use repeat(n).take(n) to repeat the individual elements and flat_map to combine those repetitions into a flat iterator:
let it = vec![1, 2, 3].into_iter();
let repeated = it.flat_map(|n| std::iter::repeat(n).take(3));
assert!(repeated.collect::<Vec<_>>() == vec![1, 1, 1, 2, 2, 2, 3, 3, 3]);
A generic version that converts any iterator into a repeated iterator might look like this (playground):
fn repeat_element<T: Clone>(it: impl Iterator<Item = T>, cnt: usize) -> impl Iterator<Item = T> {
it.flat_map(move |n| std::iter::repeat(n).take(cnt))
}

Why can I not use a slice pattern to filter a Window iterator?

I have a vector of numbers and use the windows(2) method to create an iterator that gives me neighbouring pairs. For example, the vector [1, 2, 3] is transformed into [1, 2], [2, 3]. I want to use the find method to find a slice that fulfills a specific condition:
fn step(g: u64) -> Option<(u64, u64)> {
let prime_list: Vec<u64> = vec![2, 3, 5, 7]; //For example
if prime_list.len() < 2 {
return None;
}
let res = prime_list.windows(2).find(|&&[a, b]| b - a == g)?;
//...
None
}
I get an error:
error[E0005]: refutable pattern in function argument: `&&[]` not covered
--> src/lib.rs:6:43
|
6 | let res = prime_list.windows(2).find(|&&[a, b]| b - a == g)?;
| ^^^^^^^^ pattern `&&[]` not covered
I don't know what that error means: the list cannot have less than two elements, for example. Maybe the closure parameter is wrong? I tried to vary it but that didn't change anything. a and b are being properly detected as u64 in my IDE too. What is going on here?
You, the programmer, know that each iterated value will have a length of 2, but how do you know that? You can only tell that from the prose documentation of the function:
Returns an iterator over all contiguous windows of length size. The windows overlap. If the slice is shorter than size, the iterator returns no values.
Nowhere does the compiler know this information. The implementation of Windows only states that the iterated value will be a slice:
impl<'a, T> Iterator for Windows<'a, T> {
type Item = &'a [T];
}
I'd convert the slice into an array reference, discarding any slices that were the wrong length (which you know cannot happen):
use std::convert::TryFrom;
fn step(g: u64) -> Option<(u64, u64)> {
let prime_list: Vec<u64> = vec![2, 3, 5, 7]; // For example
if prime_list.len() < 2 {
return None;
}
let res = prime_list
.windows(2)
.flat_map(<&[u64; 2]>::try_from)
.find(|&&[a, b]| b - a == g)?;
//...
None
}
See also:
How to convert a slice into an array reference?
How can I find a subsequence in a &[u8] slice?
How do I imply the type of the value when there are no type parameters or ascriptions?
Alternatively, you could use an iterator of integers and chunk it up.
See also:
Are there equivalents to slice::chunks/windows for iterators to loop over pairs, triplets etc?
At some point in the future, const generics might be stabilized and allow baking the array length into the function call and the return type.
See also:
Is it possible to control the size of an array using the type parameter of a generic?

Dereferencing Rc<Vec<T>> confusion in Rust

Why does the following code work?
use std::rc::Rc;
fn main () {
let c = vec![1, 2, 3, 4, 5];
let r = Rc::new(c);
println!("{:?}", (**r)[0]);
}
I can understand it working with single deference (println!("{:?}", (*r)[0]);). But not able to understand it working with double-dereference too.
Both, Rc and Vec implements Deref, whichs deref-method is called with the *.
let c = vec![1, 2, 3, 4, 5];
creates a Vec with the given elements with the vec!-macro.
let r = Rc::new(c);
creates a Reference counted Object from the Vector. The Vector is moved into the RC.
println!("{:?}", (**r)[0]);
This one is a bit more tricky: *r dereferences the Rc, so we get the underlying Vector. *rc dereferences the Vector as a slice. slice[0] indexes the first element of the slice, which results in the first element 1. println! finally prints the result.
It might be easier to understand what happens once we build a function prototype around the expression (**r)[0]:
fn foo<T, U>(r: T) -> i32
where
T: Deref<Target=U>,
U: Deref<Target=[i32]>,
{
(**r)[0]
}
Playground
Rc<T>, as is typical for most smart containers in Rust, implements Deref so that it can be used as an ordinary reference to the underlying value. In turn, Vec<T> implements Deref so that it can be used as a slice (Target = [T]). The explicit dereferencing *, when performed twice, applies the two conversions in sequence.
Of course, usually you wouldn't need to do this, because Vec also implements the Index operator.

Resources