Generally, .into_iter().map(…).collect()
for Vec -> Vec
transformations is the correct approach. Rust contributors even managed to put specialization magic into the standard library that can make this transformation happen in-place, for a Vec<S> -> Vec<T>
transformation if S
and T
have identical size and alignment (which is true especially of S
and T
are the same type).
As for doing this on a Vec
contained somewhere, e.g. through &mut Vec<T>
, then the code like @jwodder wrote might no longer work directly, the second trick can be to use mem::take
(or mem::replace
) to gain ownership of the Vec
first.
// assume this is all we got for access
let reference: &mut Vec<String> = &mut a.string;
// then this still works
*reference = mem::take(reference).into_iter().map(transform_string).collect();
In case of String
, usage of mem::take
would have also been an approach to apply the String -> String
transformation via &mut String
access directly.
let reference: &mut Vec<String> = &mut a.string;
// this works, too
for item in reference {
*item = transform_string(mem::take(item))
}
There’s a chance that the former code may be cheaper though (even though naively, without the specialization magic I mentioned, the latter seems better. (Note I’ve measured none of this, this is just speculation.) In any case, your example may be a stand-in for values without (cheap!) Default
values, anyways, so the former solution is more general.
All this is admittedly still a bit tedious. This is exactly the reason why most String -> String
functions are &mut String -> ()
functions instead; it’s more often than not more convenient / more generally applicable.
Noteworthy to mention would also be the create replace_with offering interesting APIs to apply T -> T
functions through a &mut T
reference, anyways, but the behavior of this in in the presence of panic means you either risk full abort of the program, or need to provide a way to create Default
-like elements, anyways (though they may be less cheap if the replace_with
API is used, as their creation is only for panicking cases then).