2015-05-10 14 views
55

Làm thế nào để nối các kết hợp sau đây của các loại:Làm cách nào để nối chuỗi?

  • strstr
  • Stringstr
  • StringString
+3

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

Trả lời

73

Khi bạn nối dây, bạn cần phải phân bổ bộ nhớ để lưu trữ kết quả. Cách dễ dàng nhất để bắt đầu với 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 tôi đã một chuỗi sở hữu mà chúng ta có thể đột biến. Điều này là hiệu quả vì nó có khả năng cho phép chúng tôi tái sử dụng cấp phát bộ nhớ. Có trường hợp tương tự cho StringString, dưới dạng &Stringcan be dereferenced as &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_string là bị ảnh hưởng (lưu ý không mut vòng loại). Có một biến thể khác là tiêu thụ số String nhưng không yêu cầu biến thể này có thể thay đổi. Đây là một implementation of the Add trait mà phải mất một String như phía bên tay trái và một &str như bên tay 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_string không còn truy cập sau khi cuộc 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, để lại 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 đều không thay đổi, vì vậy chúng tôi biết rằng chúng không được chạm vào. Nếu chúng ta muốn làm điều tương tự đối với bất kỳ sự kết hợp của String, chúng ta có thể sử dụng thực tế là String cũ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 sử dụng format! mặc dù. Bạn có thể clone one string và thêm 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); 
} 

Note - tất cả các đặc điểm kỹ thuật loại I đã làm là không cần thiết - trình biên dịch có thể suy ra tất cả các loại trò chơi tại đây. Tôi đã thêm họ chỉ đơn giản là để rõ ràng với những người mới với Rust, như tôi mong đợi câu hỏi này được phổ biến với nhóm đó!

+4

Khi bạn có '& str',' to_owned() 'nên được ưu tiên là' to_string() '; nó hiệu quả hơn, bỏ qua cơ sở hạ tầng 'std :: fmt'. –

+0

@ChrisMorgan hoàn toàn chính xác, nhưng tôi đã thấy rằng 'to_string' là dễ hiểu hơn ở đây, đặc biệt là khi tôi mong đợi đây là câu hỏi mới bắt đầu có số lượt xem cao. Tôi tình cờ thích 'vào' bản thân mình^_ ^. – Shepmaster

+1

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

15

Để ghép nhiều chuỗi thành một chuỗi, được phân cách bằng một ký tự khác, có một vài cách.

Các đẹp nhất tôi đã thấy được bằng cách sử dụng phương pháp join 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 nhiều 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ố tránh một hoặc hai phân bổ ở đây và ở đó. Vì mục đích dễ đọc, tôi thấy hai điều trên là đủ.

+0

Tài liệu 'join' được viết ở đâu? Dường như nó nằm giữa một mảng và một chuỗi. Tôi đã tìm kiếm trong tài liệu [array] (https://doc.rust-lang.org/std/primitive.array.html) và nhanh chóng bị nhầm lẫn. –

+1

@DuaneJ 'join' thực sự được gắn vào [đặc điểm' SliceContactExt'] (https://doc.rust-lang.org/std/slice/trait.SliceConcatExt.html). Đặc điểm được đánh dấu không ổn định nhưng các phương pháp của nó ổn định và [được bao gồm trong Prelude] (https://doc.rust-lang.org/std/prelude/#prelude-contents) để chúng có thể 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 phải tồn tại và tôi tưởng tượng mọi thứ sẽ thay đổi trong tương lai với nó. –

Các vấn đề liên quan