How do I convert something like this:
let mut a = vec![1, 2, 3, 4i32];
for i in a.iter_mut() {
*i += 1;
}
to a one line operation using map
and a closure?
I tried:
a.iter_mut().map(|i| *i + 1).collect::<Vec<i32>>();
The above only works if I reassign it to a
. Why is this? Is map
getting a copy of a
instead of a mutable reference? If so, how can I get a mutable reference?
Your code dereferences the variable (*i
) then adds one to it. Nowhere in there does the original value get changed.
The best way to do what you asked is to use Iterator::for_each
:
a.iter_mut().for_each(|i| *i += 1);
This gets an iterator of mutable references to the numbers in your vector. For each item, it dereferences the reference and then increments it.
You could use map
and collect
, but doing so is non-idiomatic and potentially wasteful. This uses map
for the side-effect of mutating the original value. The "return value" of assignment is the unit type ()
- an empty tuple. We use collect::<Vec<()>>
to force the Iterator adapter to iterate. This last bit ::<...>
is called the turbofish and allows us to provide a type parameter to the collect
call, informing it what type to use, as nothing else would constrain the return type.:
let _ = a.iter_mut().map(|i| *i += 1).collect::<Vec<()>>();
You could also use something like Iterator::count
, which is lighter than creating a Vec
, but still ultimately unneeded:
a.iter_mut().map(|i| *i += 1).count();
As Ry- says, using a for
loop is more idiomatic:
for i in &mut a {
*i += 1;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With