如何"作物" Rust中字符串开头的字符?

时间:2016-07-19 00:22:33

标签: string rust

我想要一个可以接受两个参数didUpdateLocations的函数并返回相同的字符串,除了字符 x 之前的字母消失。

如果我写

(string, number of letters to crop off front)

然后输出应该是:

let mut example = "stringofletters";
CropLetters(example, 3);
println!("{}", example);

我有什么方法可以做到这一点吗?

4 个答案:

答案 0 :(得分:6)

原始代码的问题:

  1. 函数使用snake_case,类型和特征使用CamelCase
  2. "foo"&str类型的字符串文字。这些可能不会改变。您将需要已分配堆的内容,例如String
  3. crop_letters(stringofletters, 3)来电{em}将stringofletters的所有权转移到该方法,这意味着您将无法再使用该变量。您必须传入可变引用(&mut)。
  4. 锈迹不是ASCII ,它们是 UTF-8 。您需要确定每个字符需要多少字节。 char_indices是一个很好的工具。
  5. 您需要处理字符串短于3个字符的情况。
  6. 一旦你有了字符串新开头的字节位置,就可以使用drain从字符串中移出一大块字节。我们只删除这些字节,让String移动剩余的字节。
  7. 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);
    }
    

    如果您实际上不需要修改原始String,请参阅Chris Emerson's answer

答案 1 :(得分:6)

在许多用途中,简单地返回输入切片是有意义的,避免任何复制。将@Shepmaster's solution转换为使用不可变切片:

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);
}

变异版本的优点是:

  • 无需复印件。如果您想要新分配的结果,可以致电cropped.to_string();但你没必要。
  • 它适用于静态字符串切片以及可变String等。

缺点是如果你真的有一个你想要修改的可变字符串,那么你需要分配一个新的String就会略微降低效率。

答案 2 :(得分:0)

我找到了这个答案,我认为这不是真的:

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);
}

答案 3 :(得分:0)

我的版本

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");
}