Как «обрезать» символы с начала строки в Rust?

string rust

1014 просмотра

3 ответа

41 Репутация автора

Мне нужна функция, которая может принимать два аргумента (string, number of letters to crop off front)и возвращать одну и ту же строку, за исключением букв перед символом x .

Если я напишу

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

тогда вывод должен быть:

ingofletters

Есть ли способ, которым я могу сделать это?

Автор: LonelyPyxel Источник Размещён: 19.07.2016 12:22

Ответы (3)


7 плюса

185875 Репутация автора

Решение

Проблемы с вашим исходным кодом:

  1. Функции использования snake_case, типы и черты использования CamelCase.
  2. "foo"строковый литерал типа &str. Они не могут быть изменены. Вам нужно что - то , что было кучи выделено, например , как String.
  3. Вызов crop_letters(stringofletters, 3)будет передавать право собственности на stringoflettersметоду, который означает , что вы не могли бы больше использовать переменную. Вы должны передать изменяемую ссылку ( &mut).
  4. Строки ржавчины не ASCII , они UTF-8 . Вам необходимо выяснить, сколько байтов требуется каждому символу. char_indicesхороший инструмент здесь
  5. Вам нужно обработать случай, когда строка короче, чем 3 символа.
  6. Как только у вас будет позиция байта нового начала строки, вы можете использовать ее drainдля перемещения фрагмента байтов из строки. Мы просто отбрасываем эти байты и позволяем 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);
}

Смотрите ответ Криса Эмерсона, если вам не нужно изменять оригинал String.

Автор: Shepmaster Размещён: 19.07.2016 12:36

7 плюса

8867 Репутация автора

Во многих случаях имеет смысл просто возвращать фрагмент ввода, избегая любой копии. Преобразование решения @ 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);
}

Преимущества перед мутантной версией:

  • Копия не требуется. Вы можете позвонить, cropped.to_string()если вы хотите вновь распределенный результат; но ты не обязан.
  • Он работает со статическими строковыми срезами, а также изменяемыми и Stringт.д.

Недостатком является то, что если у вас действительно есть изменяемая строка, которую вы хотите изменить, она будет несколько менее эффективной, так как вам потребуется выделить новую String.

Автор: Chris Emerson Размещён: 19.07.2016 10:04

0 плюса

98 Репутация автора

Я нашел этот ответ, который я не считаю действительно идиоматическим:

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);
}
Автор: Shaddy Размещён: 31.12.2018 12:14
Вопросы из категории :
32x32