The Rust way to do this is very similar to Python: use iterators! The rough equivalent to Python's list comprehension is iter::map
to get the new elements, and iter::collect
to collect into a new vector (or some other kind of collection).
So for example, if bar
is a Vec<i32>
(or any other primitive integer type) and you want to add 10 to each element, try
bar = bar.into_iter().map(|x| x + 10).collect();
(playground)
Alternatively, you could mutate the elements in-place with
bar.iter_mut().for_each(|x| *x += 10);
(playground)
This is basically like a for loop, but a bit more succinct. This is generally going to be more efficient than the first method since you don't need to allocate a new vector (a sufficiently smart compiler may be able to avoid this). The only downside is that this version is less flexible. The output still needs to be a vector; you couldn't switch to a hash set or what have you. You also wouldn't be able to keep a copy of the old vector. See below for some examples of what's possible.
fn main() {
let mut bar = vec![2, 4, 5, 6, 7];
// Overwrite the old vector
bar = bar.into_iter().map(|x| x + 10).collect();
println!("new bar: {:?}", bar);
let bar = vec![2, 4, 5, 6, 7];
// Make a completely new vector
// Note that this works only because i32 implements the Copy trait,
// so we can make copies of the elements of bar without any problems
// In more general situations, we may need to clone each element
let foo: Vec<_> = bar.iter().map(|&x| x + 10).collect();
println!("old bar: {:?} (it's still around)", bar);
println!("new foo: {:?}", foo);
use std::collections::HashSet;
let bar = vec![2, 4, 5, 6, 7];
// transform the data and collect it into a HashSet
// instead of a vector
let bar: HashSet<_> = bar.into_iter().map(|x| x + 10).collect();
println!("new bar: {:?} (note that now bar is unordered)", bar);
let mut bar = vec![2, 4, 5, 6, 7];
// Overwrite the old vector in place
bar.iter_mut().for_each(|x| *x += 10);
println!("new bar: {:?}", bar);
}
(playground)