Как объединить следующие комбинации типов:
str
иstr
String
иstr
String
иString
Как объединить следующие комбинации типов:
str
и str
String
и str
String
и String
Когда вы объединяете строки, вам необходимо выделить память для хранения результата. Начать проще всего с 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);
// After https://rust-lang.github.io/rfcs/2795-format-args-implicit-identifiers.html
// 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);
// After https://rust-lang.github.io/rfcs/2795-format-args-implicit-identifiers.html
// 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, так как я ожидаю, что этот вопрос будет популярен в этой группе!
Add
/ +
? Вы можете прикрыть это, если хотите.
- person bluss; 11.05.2015
.to_owned()
и .to_string()
было исправлено с момента вышеприведенного комментария благодаря специализации impl. Они оба теперь имеют одинаковую производительность при вызове &str
. Соответствующая фиксация: github.com/rust-lang/rust/pull/32586/files
- person chad; 23.11.2016
String
and _2 _...», поскольку это редактирование менее 6 символов, SO не позволит мне внести это изменение! (или может быть более тонкий момент, который я не понял)
- person paddyg; 17.11.2017
String
, но затем вы берете ссылку на один (&String
), который может быть приведен к &str
. Я поставил весь путь String
- ›&String
-› &str
, потому что новички могут даже не догадываться, что можно взять ссылку на String
. :-)
- person Shepmaster; 17.11.2017
Чтобы объединить несколько строк в одну строку, разделенную другим символом, есть несколько способов.
Самое приятное, что я видел, - это использование метода 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
задокументировано? Кажется, что он находится на полпути между массивом и строкой. Я просмотрел документацию по array и быстро запутался.
- person Duane J; 11.01.2018
join
фактически привязан к признаку SliceContactExt
. Признак отмечен как нестабильный, но его методы стабильны и включены в Prelude поэтому по умолчанию их можно использовать везде. Команда, похоже, хорошо понимает, что эта черта не обязательно должна существовать, и я думаю, что в будущем с ней все изменится.
- person Simon Whitehead; 11.01.2018
join
более эффективен, чем s1.to_owned().push_str(s2)
для объединения двух str
, поскольку он позволяет избежать второго распределения.
- person Ibraheem Ahmed; 19.03.2021
В Rust доступны различные методы объединения строк.
concat!()
):fn main() {
println!("{}", concat!("a", "b"))
}
Вывод приведенного выше кода:
ab
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 + &_c);
}
Вывод приведенного выше кода:
ab
abc
Using format!()
):fn main() {
let mut _a = "a".to_string();
let _b = "b".to_string();
let _c = format!("{}{}", _a, _b);
println!("{}", _c);
}
Вывод приведенного выше кода:
ab
Проверьте это и поэкспериментируйте с игровой площадкой Rust.
Я думаю, что метод concat
и здесь также следует упомянуть +
:
assert_eq!(
("My".to_owned() + " " + "string"),
["My", " ", "string"].concat()
);
и есть также макрос concat!
, но только для литералов :
let s = concat!("test", 10, 'b', true);
assert_eq!(s, "test10btrue");
+
уже упоминается в существующем ответе. (Это реализация признака Add
, которая принимает String
как левую часть и &str
как правую:)
- person Shepmaster; 14.01.2020
RFC 2795, выпущенный 27.10.2019: Предлагает поддержку неявных аргументов для выполнения того, что многие люди знают как интерполяцию строк - способ встраивания аргументов в строку для их объединения.
RFC: https://rust-lang.github.io/rfcs/2795-format-args-implicit-identifiers.html.
Статус последней проблемы можно найти здесь: https://github.com/rust-lang/rust/issues/67984
На момент написания этой статьи (2020-9-24) я считаю, что эта функция должна быть доступна в сборке Rust Nightly.
Это позволит вам выполнить конкатенацию с помощью следующего сокращения:
format_args!("hello {person}")
Это эквивалентно этому:
format_args!("hello {person}", person=person)
Также есть ящик ifmt, который предоставляет свой собственный тип интерполяции строк:
str
и&str
являются разными типами, и в 99% случаев вам следует заботиться только о&str
. Есть и другие вопросы, подробно описывающие различия между ними. - person Shepmaster   schedule 10.05.2015