Làm cách nào để chia chuỗi trong Rust?


143

Từ các tài liệu , nó không rõ ràng. Trong Java, bạn có thể sử dụng splitphương thức như vậy:

"some string 123 ffd".split("123");


@bow Có cách nào để biến nó thành mảng String thay vì vector không?
Greg

Tôi không biết cách nào để làm điều đó, ít nhất là trực tiếp. Bạn có thể phải lặp lại thủ công Splitvà đặt nó vào mảng. Tất nhiên điều này có nghĩa là số lượng các mục trong mỗi phân chia phải giống nhau vì các mảng có kích thước cố định và bạn phải có mảng được xác định trước. Tôi tưởng tượng điều này có thể rắc rối hơn là chỉ tạo ra một Vec.
cúi đầu

Câu trả lời:


158

Sử dụng split()

let mut split = "some string 123 ffd".split("123");

Điều này đưa ra một trình vòng lặp, mà bạn có thể lặp lại hoặc collect()vào một vectơ.

for s in split {
    println!("{}", s)
}
let vec = split.collect::<Vec<&str>>();
// OR
let vec: Vec<&str> = split.collect();

15
Bạn cũng có thể viết nó .collect::<Vec<_>>().
Chris Morgan

Làm thế nào để tôi có được độ dài của kết quả - let split? split.len()không tồn tại.
ア レ ッ

5
@AlexanderSupertramp Sử dụng .count(). len()chỉ dành cho các trình vòng lặp biết kích thước chính xác của chúng mà không cần phải tiêu thụ, count()tiêu thụ trình vòng lặp.
Manishearth

error: cannot borrow immutable local variable split` as mutable`
ア レ ッ ク

@AlexanderSupertramp let mut split, xin lỗi.
Manishearth

52

Có ba cách đơn giản:

  1. Bằng dấu phân cách :

    s.split("separator")  |  s.split('/')  |  s.split(char::is_numeric)
  2. Theo khoảng trắng :

    s.split_whitespace()
  3. Theo dòng mới :

    s.lines()

Kết quả của mỗi loại là một trình vòng lặp:

let text = "foo\r\nbar\n\nbaz\n";
let mut lines = text.lines();

assert_eq!(Some("foo"), lines.next());
assert_eq!(Some("bar"), lines.next());
assert_eq!(Some(""), lines.next());
assert_eq!(Some("baz"), lines.next());

assert_eq!(None, lines.next());

29

Có một phương pháp đặc biệt splitcho structString :

fn split<'a, P>(&'a self, pat: P) -> Split<'a, P> where P: Pattern<'a>

Chia theo char:

let v: Vec<&str> = "Mary had a little lamb".split(' ').collect();
assert_eq!(v, ["Mary", "had", "a", "little", "lamb"]);

Chia theo chuỗi:

let v: Vec<&str> = "lion::tiger::leopard".split("::").collect();
assert_eq!(v, ["lion", "tiger", "leopard"]);

Chia theo đóng cửa:

let v: Vec<&str> = "abc1def2ghi".split(|c: char| c.is_numeric()).collect();
assert_eq!(v, ["abc", "def", "ghi"]);

14

splittrả về một Iterator, mà bạn có thể chuyển đổi thành Vecsử dụng collect: split_line.collect::<Vec<_>>(). Đi qua một vòng lặp thay vì trả lại Vectrực tiếp có một số lợi thế:

  • splitlà lười biếng Điều này có nghĩa là nó sẽ không thực sự phân chia dòng cho đến khi bạn cần nó. Theo cách đó, sẽ không lãng phí thời gian để tách toàn bộ chuỗi nếu bạn chỉ cần một vài giá trị đầu tiên: split_line.take(2).collect::<Vec<_>>()hoặc thậm chí nếu bạn chỉ cần giá trị đầu tiên có thể được chuyển đổi thành số nguyên : split_line.filter_map(|x| x.parse::<i32>().ok()).next(). Ví dụ cuối cùng này sẽ không lãng phí thời gian khi cố xử lý "23.0" nhưng sẽ dừng xử lý ngay lập tức khi tìm thấy "1".
  • splitkhông giả định về cách bạn muốn lưu trữ kết quả. Bạn có thể sử dụng một Vec, nhưng bạn cũng có thể sử dụng bất cứ thứ gì thực hiện FromIterator<&str>, ví dụ a LinkedListhoặc a VecDeque, hoặc bất kỳ loại tùy chỉnh nào thực hiện FromIterator<&str>.

1
Cảm ơn bạn đã trả lời chi tiết, bất kỳ ý tưởng nào tại sao let x = line.unwrap().split(",").collect::<Vec<_>>();không hoạt động trừ khi nó được tách thành hai dòng riêng biệt: let x = line.unwrap();let x = x.split(",").collect::<Vec<_>>();? Thông báo lỗi cho biết:temporary value created here ^ temporary value dropped here while still borrowed
Greg

Tuy nhiên, nó hoạt động như mong đợi nếu tôi sử dụnglet x = line.as_ref().unwrap().split(",").collect::<Vec<_>>();
Greg

6

Cũng có split_whitespace()

fn main() {
    let words: Vec<&str> = "   foo   bar\t\nbaz   ".split_whitespace().collect();
    println!("{:?}", words);
    // ["foo", "bar", "baz"] 
}
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.