Làm thế nào để tôi nối chuỗi?


199

Làm cách nào để kết hợp các loại kết hợp sau:

  • strstr
  • Stringstr
  • StringString

14
Lưu ý rằng str&strcác loại khác nhau và trong 99% thời gian, bạn chỉ nên quan tâm &str. Có những câu hỏi khác chi tiết về sự khác biệt giữa chúng.
Người quản lý

Câu trả lời:


235

Khi bạn nối chuỗi, bạn cần phân bổ bộ nhớ để lưu trữ kết quả. Cách dễ nhất để bắt đầu là 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);
}

Ở đây, chúng ta có một chuỗi sở hữu mà chúng ta có thể đột biến. Điều này rất hiệu quả vì nó có khả năng cho phép chúng ta sử dụng lại việc cấp phát bộ nhớ. Có một trường hợp tương tự cho StringString, như &String có thể được quy định là&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);
}

Sau này, another_owned_stringkhông bị ảnh hưởng (lưu ý không có mutvòng loại). Có một biến thể mà tiêu thụ các Stringnhưng không đòi hỏi nó là có thể thay đổi. Đây là một cách thực hiện các Addđặc điểm lấy Stringbên trái và &strbên phải:

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

Lưu ý rằng owned_stringkhông còn truy cập được sau khi gọi đến +.

Điều gì sẽ xảy ra nếu chúng ta muốn tạo ra một chuỗi mới, khiến cả hai không bị ảnh hưởng? Cách đơn giản nhất là sử dụng format!:

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

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

Lưu ý rằng cả hai biến đầu vào là bất biến, vì vậy chúng tôi biết rằng chúng không bị chạm. Nếu chúng tôi muốn làm điều tương tự cho bất kỳ sự kết hợp nào String, chúng tôi có thể sử dụng thực tế Stringcũng có thể được định dạng:

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

Bạn không cần phải sử dụng format!mặc dù. Bạn có thể sao chép một chuỗi và nối chuỗi khác vào chuỗi mới:

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

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

Lưu ý - tất cả các đặc tả loại tôi đã làm là dư thừa - trình biên dịch có thể suy ra tất cả các loại đang chơi ở đây. Tôi đã thêm chúng đơn giản để rõ ràng với những người mới biết đến Rust, vì tôi hy vọng câu hỏi này sẽ phổ biến với nhóm đó!


2
Bạn nghĩ gì về Add/ +biểu tượng? Bạn có thể che nó nếu bạn muốn.
bluss

Có thể điều đó đủ đơn giản, nhưng để hiểu nó đòi hỏi phải xem các chữ ký loại có thể có cho Thêm bằng Chuỗi.
bluss

Cảm ơn! Bạn có thể đi sâu hơn một chút vào cách & Chuỗi có thể được hủy đăng ký dưới dạng & str không? Phần nào trong quá trình thực hiện của nó cho phép và / hoặc nó nói điều này trong tài liệu ở đâu?
jsalter

1
@jsalter đó là một chủ đề khá riêng biệt, vì vậy nó có thể tốt như một câu hỏi cấp cao khác. Tôi đã cập nhật để liên kết đến các tài liệu phù hợp (gần nhất có thể, ít nhất là ...)
Người quản lý

10
@ChrisMorgan Cần lưu ý rằng sự khác biệt .to_owned().to_string()đã được khắc phục kể từ khi nhận xét ở trên nhờ chuyên môn hóa. Bây giờ cả hai đều có hiệu suất như nhau khi được gọi trên a &str. Cam kết có liên quan: github.com/rust-lang/rust/pull/32586/files
chad

49

Để nối nhiều chuỗi thành một chuỗi, cách nhau bởi một ký tự khác, có một vài cách.

Điều tốt nhất tôi đã thấy là sử dụng joinphương thức trên một mảng:

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

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

Tùy thuộc vào trường hợp sử dụng của bạn, bạn cũng có thể thích kiểm soát hơn:

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

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

Có một số cách thủ công hơn tôi đã thấy, một số cách tránh một hoặc hai phân bổ ở đây và ở đó. Đối với mục đích dễ đọc, tôi thấy hai điều trên là đủ.


Trong trường hợp được joinghi nhận? Nó dường như ngồi giữa một mảng và một chuỗi. Tôi đã tìm kiếm thông qua các tài liệu mảng và nhanh chóng bối rối.
Duane J

3
@DuaneJ joinlà thực sự gắn liền với những SliceContactExtđặc điểm . Đặc điểm được đánh dấu là không ổn định nhưng các phương thức của nó ổn định và được bao gồm trong Prelude để chúng có thể được sử dụng ở mọi nơi theo mặc định. Nhóm nghiên cứu dường như nhận thức rõ đặc điểm này không cần tồn tại và tôi tưởng tượng mọi thứ sẽ thay đổi trong tương lai với nó.
Simon Whitehead

9

Tôi nghĩ rằng concatphương pháp đó và +cũng nên được đề cập ở đây:

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

và cũng có concat!macro nhưng chỉ dành cho chữ:

let s = concat!("test", 10, 'b', true);
assert_eq!(s, "test10btrue");

+đã được đề cập trong một câu trả lời hiện có . ( Đây là cách thực hiện Addđặc điểm lấy Stringbên trái và bên phải &strlàm bên phải :)
Người quản lý

Đúng, câu trả lời hiện tại rất rộng, tôi không nhận thấy.
nhạy cảm vào

6

Những cách đơn giản để nối chuỗi trong RUST

Có nhiều phương thức khác nhau có sẵn trong RUST để nối chuỗi

Phương pháp đầu tiên (Sử dụng concat!()):

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

Đầu ra của đoạn mã trên là:

ab


Phương thức thứ hai (sử dụng push_str()+toán tử):

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

Đầu ra của đoạn mã trên là:

ab

abc


Phương thức thứ ba ( Using format!()):

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

Đầu ra của đoạn mã trên là:

ab

kiểm tra và thử nghiệm với sân chơi Rust


Câu trả lời này không thêm bất cứ điều gì mới vào câu trả lời hiện có.
Mục sư
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.