I have a nested Vec<Vec<f64>> in Rust, and I want to multiply each f64 in place by a value DT. I am currently doing:
dcm_dot.iter_mut().map(|a| a.iter_mut().map(|b| * b * DT));
This works, however, I am getting a lazy iterator warning, that the .map()s must be consumed. Is there a more idiomatically correct way to do this?
Iterators in Rust are lazy so unless you use the result of the .map(),
the closure inside will not even be executed.
In order to ensure that your code actually changes the Vec, you should use .for_each() instead.
Playground
Related
What is the idiomatic Rust method for R's mapply()? mapply() takes a function, and iterables, and calls the function with the first elements of each iterable as arguments, the second elements, etc.
I am currently using the future_mapply() function in R from the future library to do it in parallel as well, but am finding it to be too slow.
Any help is appreciated.
There is no direct equivalent, as Rust doesn't deal with variadic functions or abstract over tuples of different lengths (better to ignore HLists here). If your number of iterators is fixed, you can use it1.zip(it2).zip(it3).map(|((e1, e2), e3)| f(e1, e2, e3)) or itertools::izip!.
If all your iterators have the same type (i.e. can be put into a Vec) and the function to be applied is fine with receiving the elements as a Vec, you could do something like
std::iter::from_fn(move || {
iter_vec // the vector with your input iterators
.iter_mut()
.map(Iterator::next)
.collect::<Option<Vec<_>>>()
}).map(f)
Playground
I think you'll have to describe your problem a bit more for your question to be properly answered.
This is what I'm trying to do, but it doesn't work:
use std::collections::VecDeque;
let mut x: VecDeque<String> = VecDeque::new();
x.push_back("bye".to_string());
x.push_front("hello".to_string());
x.join(" "); // doesn't compile!
I'm expecting hello bye as a result.
What is the right way?
The simplest option is probably to convert the VecDeque .into() a Vec, though as the documentation says:
This never needs to re-allocate, but does need to do O(n) data movement if the circular buffer doesn’t happen to be at the beginning of the allocation.
so ymmv on the efficiency front.
Alternatively, add a dependency on itertools which has a number of nice utilities including a join method (and also for your case a helper join function so you don't even need to convert the collection to an iterator).
I have a question with regards to functional rust, and how the core lib functions work. It seems they return different things, depending on their ordering.
As an example, I have made a simple function that doubles numbers, and takes only even numbers. So, a map and a filter is needed. It looks like this:
However when I change the order of the map/filter, the return of filter changes, like so:
I understand the error, and that I need to dereference the variable, but I don't know why this change happens. Can someone explain to me what is going on here?
slice::iter returns a std::slice::Iter. That structure implements Iterator<Item = &T>, so it yields references.
Iterator::filter returns a std::iter::Filter, which implements Iterator<Item = I::Item>, aka it yields whatever the iterator it transforms yields. So in the second snippet, since iter() yields &i32, iter().filter(..) yields &i32.
In the first snippet however there's a Iterator::map between the two. That yields whatever the mapping function returns, which in your case is an i32. Therefore the filter which follows matches that, and yields an i32 as well.
The last pieces of the puzzle are that:
since it doesn't take ownership filter's callback receives a reference to the input value, even if that value is already a reference, so if it's transforming an Iterator<Item=&T> it receives an &&T
while the . operator will dereference as many times as necessary, other operators will not dereference at all
because references are so common in Rust, rather than implement only i32 % i32 the stdlib also implements:
&i32 % i32
i32 % &i32
&i32 % &i32
However that's where the stdlib stops, there is no impl Rem<i32> for &&i32. Therefore no &&i32 % i32, therefore your second version can not find a trait implementation to call.
FWIW while you can of course dereference in the filter callback, there's an iterator adapter to avoid working with references to simple types (as, as you've discovered, that's often less convenient; it's also commonly less efficient): Iterator::copied will transform an Iterator<Item=&T> into Iterator<Item=T> as long as T is Copy (meaning trivially copiable and usually fairly small, like an integer).
I have been searching to find parallelizes map in rust most answer point to rayon crate so I wonder if std::iter::map iterate sequentially by default?
I wonder if std::iter::map iterate sequentially by default?
It does
Rust iterators are lazy, meaning that nothing is computed unless asked explicitly. And they are computed one by one until the iterator is exhausted.
Map , from the documentation:
An iterator that maps the values of iter with f
Is an iterator adaptor, it will apply a transformation function on each item of the iterator one by one (when requested, through the next method).
I can not find a way to collect the values of a HashMap into a Vec in the documentation. I have score_table: HashMap<Id, Score> and I want to get all the Scores into all_scores: Vec<Score>.
I was tempted to use the values method (all_scores = score_table.values()), but it does not work since values is not a Vec.
I know that Values implements the ExactSizeIterator trait, but I do not know how to collect all values of an iterator into a vector without manually writing a for loop and pushing the values in the vector one after one.
I also tried to use std::iter::FromIterator; but ended with something like:
all_scores = Vec::from_iter(score_table.values());
expected type `std::vec::Vec<Score>`
found type `std::vec::Vec<&Score>`
Thanks to Hash map macro refuses to type-check, failing with a misleading (and seemingly buggy) error message?, I changed it to:
all_scores = Vec::from_iter(score_table.values().cloned());
and it does not produce errors to cargo check.
Is this a good way to do it?
The method Iterator.collect is designed for this specific task. You're right in that you need .cloned() if you want a vector of actual values instead of references (unless the stored type implements Copy, like primitives), so the code looks like this:
all_scores = score_table.values().cloned().collect();
Internally, collect() just uses FromIterator, but it also infers the type of the output. Sometimes there isn't enough information to infer the type, so you may need to explicitly specify the type you want, like so:
all_scores = score_table.values().cloned().collect::<Vec<Score>>();
If you don't need score_table anymore, you can transfer the ownership of Score values to all_scores by:
let all_scores: Vec<Score> = score_table.into_iter()
.map(|(_id, score)| score)
.collect();
This approach will be faster and consume less memory than the clone approach by #apetranzilla. It also supports any struct, not only structs that implement Clone.
There are three useful methods on HashMaps, which all return iterators:
values() borrows the collection and returns references (&T).
values_mut() gives mutable references &mut T which is useful to modify elements of the collection without destroying score_table.
into_values() gives you the elements directly: T! The iterator takes ownership of all the elements. This means that score_table no longer owns them, so you can't use score_table anymore!
In your example, you call values() to get &T references, then convert them to owned values T via a clone().
Instead, if we have an iterator of owned values, then we can convert it to a Vec using Iterator::collect():
let all_scores: Vec<Score> = score_table.into_values().collect();
Sometimes, you may need to specify the collecting type:
let all_scores = score_table.into_values().collect::<Vec<Score>>();