[英]How to “crop” characters off the beginning of a string in Rust?
I want a function that can take two arguments (string, number of letters to crop off front)
and return the same string except with the letters before character x gone.我想要一个函数,它可以接受两个参数
(string, number of letters to crop off front)
要从(string, number of letters to crop off front)
并返回相同的字符串,除了字符x之前的字母消失了。
If I write如果我写
let mut example = "stringofletters";
CropLetters(example, 3);
println!("{}", example);
then the output should be:那么输出应该是:
ingofletters
Is there any way I can do this?有什么办法可以做到这一点吗?
In many uses it would make sense to simply return a slice of the input, avoiding any copy.在许多用途中,简单地返回输入的一部分是有意义的,避免任何复制。 Converting @Shepmaster's solution to use immutable slices:
将@Shepmaster 的解决方案转换为使用不可变切片:
fn crop_letters(s: &str, pos: usize) -> &str {
match s.char_indices().skip(pos).next() {
Some((pos, _)) => &s[pos..],
None => "",
}
}
fn main() {
let example = "stringofletters"; // works with a String if you take a reference
let cropped = crop_letters(example, 3);
println!("{}", cropped);
}
Advantages over the mutating version are:与变异版本相比的优点是:
cropped.to_string()
if you want a newly allocated result;cropped.to_string()
; but you don't have to.String
etc.String
等。 The disadvantage is that if you really do have a mutable string you want to modify, it would be slightly less efficient as you'd need to allocate a new String
.缺点是,如果您确实有一个要修改的可变字符串,那么效率会稍低一些,因为您需要分配一个新的
String
。
Issues with your original code:原始代码的问题:
snake_case
, types and traits use CamelCase
.snake_case
,类型和特征使用CamelCase
。"foo"
is a string literal of type &str
. "foo"
是&str
类型的字符串文字。 These may not be changed.String
.String
。crop_letters(stringofletters, 3)
would transfer ownership of stringofletters
to the method, which means you wouldn't be able to use the variable anymore.crop_letters(stringofletters, 3)
会将stringofletters
所有权stringofletters
给该方法,这意味着您将无法再使用该变量。 You must pass in a mutable reference ( &mut
).&mut
)。char_indices
is a good tool here. char_indices
是一个很好的工具。drain
to move a chunk of bytes out of the string.drain
将一大块字节移出字符串。 We just drop these bytes and let the String
move over the remaining bytes.String
移动到剩余的字节上。fn crop_letters(s: &mut String, pos: usize) {
match s.char_indices().nth(pos) {
Some((pos, _)) => {
s.drain(..pos);
}
None => {
s.clear();
}
}
}
fn main() {
let mut example = String::from("stringofletters");
crop_letters(&mut example, 3);
assert_eq!("ingofletters", example);
}
See Chris Emerson's answer if you don't actually need to modify the original String
.如果您实际上不需要修改原始
String
请参阅Chris Emerson 的回答。
I found this answer which I don't consider really idiomatic:我找到了这个我认为不太惯用的答案:
fn crop_with_allocation(string: &str, len: usize) -> String {
string.chars().skip(len).collect()
}
fn crop_without_allocation(string: &str, len: usize) -> &str {
// optional length check
if string.len() < len {
return &"";
}
&string[len..]
}
fn main() {
let example = "stringofletters"; // works with a String if you take a reference
let cropped = crop_with_allocation(example, 3);
println!("{}", cropped);
let cropped = crop_without_allocation(example, 3);
println!("{}", cropped);
}
my version我的版本
fn crop_str(s: &str, n: usize) -> &str {
let mut it = s.chars();
for _ in 0..n {
it.next();
}
it.as_str()
}
#[test]
fn test_crop_str() {
assert_eq!(crop_str("123", 1), "23");
assert_eq!(crop_str("ЖФ1", 1), "Ф1");
assert_eq!(crop_str("ЖФ1", 2), "1");
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.