有没有办法 trim 一个字符串而不分配另一个字符串?
Is there a way to trim a String without allocating another one?
我有一个 CSV 格式的文件,其中第一列数据代表项目代码,可选择以 "UNIUNI"
结尾或这些字符的大小写混合,通过条形码 reader 加载。我需要 trim 离开最后 "UNI"
秒。
我写了这个函数:
fn main() {
// Ok: from "9846UNIUNI" to "9846"
println!("{}", read_csv_rilev("9846UNIUNI".to_string()));
// Wrong: from "9846uniuni" to "9846"
println!("{}", read_csv_rilev("9846uniuni".to_string()));
}
fn read_csv_rilev(code: String) -> String {
code
//.to_uppercase() /*Unstable feature in Rust 1.1*/
.trim_right_matches("UNI")
.to_string()
}
理想的函数签名如下所示:
fn read_csv_rilev(mut s: &String)
但对 String
执行就地操作可能不是一个好主意。事实上,在 Rust 标准库中,除了 String::pop()
.
之外,没有任何东西可以做到这一点
but probably an in-place action on a String is not a good idea.
binding 在 mut s: &String
中是可变的,而不是字符串本身。如果你想改变字符串本身,你会选择 s: &mut String
。
也就是说,我认为标准库中没有任何东西可以做到这一点。
Is there a way to trim a String
without allocating another one?
是的,您可以使用 truncate
删除字符串的尾部:
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);
}
您根本不需要弄乱分配的字符串。您可以使用相同的逻辑并制作字符串的连续子片段。这基本上就是 trim_right_matches
的工作原理,但不太通用:
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);
}
一般来说,我可能会选择第二种解决方案。
另一个解决方案是使用 owning_ref
crate,它可以让你 return 同时 &str
和它的支持 String
:
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"))
}
我知道这是旧的,但有一个很好的两行,trim_right_matches 现在已弃用,但是 trim_end_matches() returns 一个 &str 与你想要的长度
fn read_csv_rilev(code: &mut String) {
// code.to_uppercase();
let l = code.trim_end_matches("UNI").len();
code.truncate(l);
}
我有一个 CSV 格式的文件,其中第一列数据代表项目代码,可选择以 "UNIUNI"
结尾或这些字符的大小写混合,通过条形码 reader 加载。我需要 trim 离开最后 "UNI"
秒。
我写了这个函数:
fn main() {
// Ok: from "9846UNIUNI" to "9846"
println!("{}", read_csv_rilev("9846UNIUNI".to_string()));
// Wrong: from "9846uniuni" to "9846"
println!("{}", read_csv_rilev("9846uniuni".to_string()));
}
fn read_csv_rilev(code: String) -> String {
code
//.to_uppercase() /*Unstable feature in Rust 1.1*/
.trim_right_matches("UNI")
.to_string()
}
理想的函数签名如下所示:
fn read_csv_rilev(mut s: &String)
但对 String
执行就地操作可能不是一个好主意。事实上,在 Rust 标准库中,除了 String::pop()
.
but probably an in-place action on a String is not a good idea.
binding 在 mut s: &String
中是可变的,而不是字符串本身。如果你想改变字符串本身,你会选择 s: &mut String
。
也就是说,我认为标准库中没有任何东西可以做到这一点。
Is there a way to trim a
String
without allocating another one?
是的,您可以使用 truncate
删除字符串的尾部:
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);
}
您根本不需要弄乱分配的字符串。您可以使用相同的逻辑并制作字符串的连续子片段。这基本上就是 trim_right_matches
的工作原理,但不太通用:
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);
}
一般来说,我可能会选择第二种解决方案。
另一个解决方案是使用 owning_ref
crate,它可以让你 return 同时 &str
和它的支持 String
:
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"))
}
我知道这是旧的,但有一个很好的两行,trim_right_matches 现在已弃用,但是 trim_end_matches() returns 一个 &str 与你想要的长度
fn read_csv_rilev(code: &mut String) {
// code.to_uppercase();
let l = code.trim_end_matches("UNI").len();
code.truncate(l);
}