Bagaimana cara menyatukan senar?

199

Bagaimana saya menggabungkan kombinasi tipe berikut:

  • str dan str
  • String dan str
  • String dan String
jsalter
sumber
14
Perhatikan bahwa strdan &strada berbagai jenis dan untuk 99% dari waktu, Anda hanya harus peduli &str. Ada pertanyaan lain yang merinci perbedaan di antara mereka.
Shepmaster

Jawaban:

235

Ketika Anda menggabungkan string, Anda perlu mengalokasikan memori untuk menyimpan hasilnya. Cara termudah untuk memulai adalah Stringdan &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);
}

Di sini, kami memiliki string yang dimiliki yang dapat kami mutasi. Ini efisien karena berpotensi memungkinkan kita untuk menggunakan kembali alokasi memori. Ada kasus yang sama untuk Stringdan String, seperti yang &String dapat direferensikan sebagai&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);
}

Setelah ini, another_owned_stringtidak tersentuh (perhatikan tidak ada mutkualifikasi). Ada varian lain yang mengkonsumsi tersebut Stringtetapi tidak memerlukan itu bisa berubah. Ini adalah implementasi dari Addsifat yang mengambil Stringsebagai sebagai sisi kiri dan &strsebagai sebagai sisi kanan:

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

Perhatikan bahwa owned_stringtidak lagi dapat diakses setelah panggilan ke +.

Bagaimana jika kita ingin menghasilkan string baru, membiarkan keduanya tidak tersentuh? Cara paling sederhana adalah dengan menggunakan format!:

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

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

Perhatikan bahwa kedua variabel input tidak dapat diubah, jadi kami tahu bahwa mereka tidak tersentuh. Jika kita ingin melakukan hal yang sama untuk kombinasi apa pun String, kita dapat menggunakan fakta yang Stringjuga dapat diformat:

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

Anda tidak harus menggunakannya format!. Anda dapat mengkloning satu string dan menambahkan string lainnya ke string baru:

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

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

Catatan - semua spesifikasi tipe yang saya lakukan adalah redundan - kompiler dapat menyimpulkan semua tipe yang dimainkan di sini. Saya menambahkannya hanya untuk menjadi jelas bagi orang yang baru mengenal Rust, karena saya berharap pertanyaan ini menjadi populer di grup itu!

Shepmaster
sumber
2
Apa yang Anda pikirkan tentang Add/ +simbol? Anda bisa menutupinya jika Anda mau.
Bluss
Mungkin itu cukup sederhana, tetapi memahaminya membutuhkan melihat jenis tanda tangan yang mungkin untuk Add with String.
Bluss
Terima kasih! Apakah Anda bisa masuk sedikit lebih dalam tentang bagaimana & String dapat dereferensi sebagai a & str? Bagian mana dari implementasinya yang mengizinkan itu dan / atau di mana ia mengatakan ini dalam dokumen?
jsalter
1
@ jsalter itu topik yang cukup terpisah, jadi mungkin baik sebagai pertanyaan tingkat atas lainnya. Saya telah memperbarui untuk menautkan ke dokumen yang sesuai (sedekat mungkin, setidaknya ...)
Shepmaster
10
@ChrisMorgan Perlu dicatat bahwa perbedaan .to_owned()dan .to_string()telah diperbaiki sejak komentar di atas berkat penerapan spesialisasi. Mereka berdua sekarang memiliki kinerja yang sama ketika dipanggil &str. Komit yang relevan: github.com/rust-lang/rust/pull/32586/files
chad
49

Untuk menggabungkan beberapa string menjadi satu string, dipisahkan oleh karakter lain, ada beberapa cara.

Yang terbaik yang pernah saya lihat adalah menggunakan joinmetode pada array:

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

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

Tergantung pada kasus penggunaan Anda, Anda mungkin juga lebih suka kontrol yang lebih besar:

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

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

Ada beberapa cara manual yang telah saya lihat, beberapa menghindari satu atau dua alokasi di sana-sini. Untuk tujuan keterbacaan saya menemukan dua di atas sudah cukup.

Simon Whitehead
sumber
Di mana joindidokumentasikan? Tampaknya berada di tengah-tengah antara Array dan String. Saya mencari melalui dokumentasi array dan dengan cepat bingung.
Duane J
3
@DuaneJ joinsebenarnya melekat pada SliceContactExtsifat tersebut . Ciri tersebut ditandai tidak stabil tetapi metodenya stabil dan termasuk dalam Prelude sehingga mereka dapat digunakan di mana saja secara default. Tim tampaknya sangat menyadari sifat ini tidak perlu ada dan saya membayangkan hal-hal akan berubah di masa depan dengannya.
Simon Whitehead
9

Saya pikir concatmetode itu dan +harus disebutkan di sini juga:

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

dan ada juga concat!makro tetapi hanya untuk literal:

let s = concat!("test", 10, 'b', true);
assert_eq!(s, "test10btrue");
suside
sumber
+sudah disebutkan dalam jawaban yang ada . ( Ini merupakan implementasi dari Addsifat yang mengambil Stringsebagai sisi kiri dan &strsebagai sisi kanan: )
Shepmaster
Benar, jawaban yang ada begitu luas sehingga saya tidak menyadarinya.
suside
6

Cara sederhana untuk menggabungkan string di RUST

Ada berbagai metode yang tersedia di RUST untuk menggabungkan string

Metode pertama (Menggunakan concat!()):

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

Output dari kode di atas adalah:

ab


Metode kedua (menggunakan push_str()dan +operator):

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

Output dari kode di atas adalah:

ab

abc


Metode ketiga ( Using format!()):

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

Output dari kode di atas adalah:

ab

memeriksanya dan bereksperimen dengan Rust play ground

ASHWIN RAJEEV
sumber
Jawaban ini tidak menambahkan sesuatu yang baru ke jawaban yang ada.
Shepmaster