Is there a way to trim a String without allocating another one?
but probably an in-place action on a String is not a good idea.
The binding is mutable in mut s: &String
, not the string itself. You would take s: &mut String
if you wanted to mutate the string itself.
That said, I don't think there's anything in the standard library to do this.
I know this is old, but there is a nice two liner, trim_right_matches is deprecated now, but trim_end_matches() returns a &str with the length you want
fn read_csv_rilev(code: &mut String) {
// code.to_uppercase();
let l = code.trim_end_matches("UNI").len();
code.truncate(l);
}
Is there a way to trim a
String
without allocating another one?
Yes, you can use truncate
to remove trailing parts of the string:
const TRAILER: &'static str = "UNI";
fn read_csv_rilev(s: &mut String) {
while s.ends_with(TRAILER) {
let len = s.len();
let new_len = len.saturating_sub(TRAILER.len());
s.truncate(new_len);
}
}
fn main() {
let mut code = "Hello WorldUNIUNIUNI".into();
read_csv_rilev(&mut code);
assert_eq!("Hello World", code);
}
You don't need to mess with the allocated string at all. You can use the same logic and make successive subslices of the string. This is basically how trim_right_matches
works, but a bit less generic:
const TRAILER: &'static str = "UNI";
fn read_csv_rilev(mut s: &str) -> &str {
while s.ends_with(TRAILER) {
let len = s.len();
let new_len = len.saturating_sub(TRAILER.len());
s = &s[..new_len];
}
s
}
fn main() {
let code = "Hello WorldUNIUNIUNI";
let truncated = read_csv_rilev(code);
assert_eq!("Hello World", truncated);
}
In general, I'd probably go with the second solution.
Another solution is to use the owning_ref
crate, which lets you return both a &str
and its backing String
at the same time:
extern crate owning_ref;
use owning_ref::StringRef;
fn read_csv_rilev(code: String) -> StringRef {
StringRef::new(code).map(|s| s.trim_right_matches("UNI"))
}