Как да свържа следните комбинации от типове:
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
и &String
...", тъй като това е редакция с по-малко от 6 знака, ТАКА че няма да ми позволи да направя тази промяна! (или може да е по-фин момент, който не съм разбрал)
- 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
? Изглежда, че се намира по средата между масив и низ. Търсих в документацията за масив и бързо се обърках.
- 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
абв
Using format!()
):fn main() {
let mut _a = "a".to_string();
let _b = "b".to_string();
let _c = format!("{}{}", _a, _b);
println!("{}", _c);
}
Резултатът от горния код е:
ab
Вижте го и експериментирайте с Rust playground.
Мисля, че методът 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, издаден 2019-10-27: Предлага поддръжка за имплицитни аргументи за извършване на това, което много хора биха познали като интерполация на низове – начин за вграждане на аргументи в низ, за да ги свърже.
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 crate, който предоставя свой собствен вид интерполация на низове:
str
и&str
са различни типове и през 99% от времето трябва да се интересувате само от&str
. Има и други въпроси, описващи разликите между тях. - person Shepmaster   schedule 10.05.2015