Как объединить строки?

199

Как объединить следующие комбинации типов:

  • str и str
  • String и str
  • String и String
jsalter
источник
14
Обратите внимание, что strи &strэто разные типы и в 99% случаев вам нужно только позаботиться &str. Есть и другие вопросы, детализирующие различия между ними.
Шепмастер

Ответы:

235

Когда вы объединяете строки, вам нужно выделить память для хранения результата. Проще всего начать с Stringи &str:

fn main() {
    let mut owned_string: String = "hello ".to_owned();
    let borrowed_string: &str = "world";

    owned_string.push_str(borrowed_string);
    println!("{}", owned_string);
}

Здесь у нас есть собственная строка, которую мы можем изменить. Это эффективно, поскольку потенциально позволяет нам повторно использовать выделение памяти. Там аналогичный случай для Stringи String, как &String можно разыменовать как&str .

fn main() {
    let mut owned_string: String = "hello ".to_owned();
    let another_owned_string: String = "world".to_owned();

    owned_string.push_str(&another_owned_string);
    println!("{}", owned_string);
}

После этого another_owned_stringостается нетронутым (примечание без mutуточнения). Там еще один вариант , который потребляетString , но не требует от него быть изменяемыми. Это реализация Addчерты, которая принимает Stringкак левую сторону, а &strкак правую:

fn main() {
    let owned_string: String = "hello ".to_owned();
    let borrowed_string: &str = "world";

    let new_owned_string = owned_string + borrowed_string;
    println!("{}", new_owned_string);
}

Обратите внимание, что owned_stringбольше не доступно после звонка +.

Что если мы хотим создать новую строку, оставив обе нетронутыми? Самый простой способ - использовать format!:

fn main() {
    let borrowed_string: &str = "hello ";
    let another_borrowed_string: &str = "world";

    let together = format!("{}{}", borrowed_string, another_borrowed_string);
    println!("{}", together);
}

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

fn main() {
    let owned_string: String = "hello ".to_owned();
    let another_owned_string: String = "world".to_owned();

    let together = format!("{}{}", owned_string, another_owned_string);
    println!("{}", together);
}

Вы не должны использовать format!все же. Вы можете клонировать одну строку и добавить другую строку к новой строке:

fn main() {
    let owned_string: String = "hello ".to_owned();
    let borrowed_string: &str = "world";

    let together = owned_string.clone() + borrowed_string;
    println!("{}", together);
}

Примечание: все спецификации типов, которые я сделал, являются избыточными - компилятор может вывести здесь все типы в игре. Я добавил их просто для ясности новичкам в Rust, так как я ожидаю, что этот вопрос будет популярен в этой группе!

Shepmaster
источник
2
Что вы думаете о Add/ +символ? Вы можете покрыть это, если хотите.
блюсс
Возможно, это достаточно просто, но чтобы понять это, нужно посмотреть на возможные сигнатуры типов для Add with String.
блюсс
Спасибо! Можете ли вы углубиться в то, как & String можно разыменовать как & str? Какая часть его реализации разрешает это и / или где говорится в документе?
jsalter
1
@jsalter - это довольно отдельная тема, так что это может быть хорошо, как еще один вопрос высшего уровня. Я обновил ссылку на соответствующие документы (как можно ближе, по крайней мере ...)
Shepmaster
10
@ChrisMorgan Следует отметить, что расхождение .to_owned()и .to_string()было исправлено с момента вышеупомянутого комментария благодаря подразумеваемой специализации. Теперь они оба имеют одинаковую производительность при вызове &str. Соответствующий коммит: github.com/rust-lang/rust/pull/32586/files
chad
49

Чтобы объединить несколько строк в одну строку, разделенную другим символом, существует несколько способов.

Самое приятное, что я видел, это использование joinметода в массиве:

fn main() {
    let a = "Hello";
    let b = "world";
    let result = [a, b].join("\n");

    print!("{}", result);
}

В зависимости от вашего варианта использования вы также можете предпочесть больше контроля:

fn main() {
    let a = "Hello";
    let b = "world";
    let result = format!("{}\n{}", a, b);

    print!("{}", result);
}

Я видел еще несколько ручных способов, некоторые избегают одного или двух распределений здесь и там. Для удобства чтения я считаю, что вышеупомянутых двух будет достаточно.

Саймон Уайтхед
источник
Где joinдокументировано? Кажется, он находится на полпути между массивом и строкой. Я искал документацию по массиву и быстро растерялся.
Duane J
3
@DuaneJ joinна самом деле привязан к этой SliceContactExtчерте . Черта помечена как нестабильная, но ее методы стабильны и включены в Prelude, поэтому по умолчанию их можно использовать везде. Команда, кажется, хорошо знает, что эта черта не должна существовать, и я думаю, что в будущем все изменится.
Саймон Уайтхед
9

Я думаю, что этот concatметод и +должен быть упомянут здесь также:

assert_eq!(
  ("My".to_owned() + " " + "string"),
  ["My", " ", "string"].concat()
);

и есть также concat!макрос, но только для литералов:

let s = concat!("test", 10, 'b', true);
assert_eq!(s, "test10btrue");
suside
источник
+уже упоминалось в существующем ответе . ( Это реализация Addпризнака , который принимает в Stringкачестве стороны левой стороны , и &strкак с правой стороны: )
Shepmaster
Правда, существующий ответ настолько широк, что я не заметил.
suside
6

Простые способы объединения строк в RUST

В RUST доступны различные методы для объединения строк

Первый способ (Использование concat!()):

fn main() {
    println!("{}", concat!("a", "b"))
}

Вывод вышеуказанного кода:

аб


Второй метод (использование push_str()и +оператор):

fn main() {
    let mut _a = "a".to_string();
    let _b = "b".to_string();
    let _c = "c".to_string();

    _a.push_str(&_b);
    
    println!("{}", _a);
 
    println!("{}", _a + &_b);
}

Вывод вышеуказанного кода:

аб

азбука


Третий метод ( Using format!()):

fn main() {
    let mut _a = "a".to_string();
    let _b = "b".to_string();
    let _c = format!("{}{}", _a, _b);
    
    println!("{}", _c);
}

Вывод вышеуказанного кода:

аб

проверить это и поэкспериментировать с игровой площадкой Rust

АШВИН РАДЖЕЕВ
источник
Этот ответ не добавляет ничего нового к существующим ответам.
Шепмейстер