如何在Rust中分割字符串?


143

文档中尚不清楚。在Java中,您可以使用如下split方法:

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


@bow有没有办法使它成为String数组而不是向量?
格雷格,

我至少没有直接的办法。您可能必须手动遍历Split并将其设置到数组中。当然,这意味着每个拆分中的项目数必须相同,因为数组是固定大小的,因此您必须事先定义数组。我想这可能比简单地创建一个更麻烦Vec
鞠躬

Answers:


158

split()

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

这提供了一个迭代器,您可以将其循环或collect()向量化。

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

15
您也可以编写它.collect::<Vec<_>>()
克里斯·摩根

我如何得到结果的长度- let splitsplit.len()不存在。
2014年

5
@AlexanderSupertramp使用.count()len()仅适用于知道不需要消耗其确切大小count()的迭代器,它会消耗迭代器。
Manishearth

error: cannot borrow immutable local variable split`作为mutable`
アレックス

@AlexanderSupertramp let mut split,对不起。
Manishearth 2014年

53

有三种简单的方法:

  1. 分隔符

    s.split("separator")  |  s.split('/')  |  s.split(char::is_numeric)
  2. 通过空格

    s.split_whitespace()
  3. 通过换行符

    s.lines()

每种类型的结果都是一个迭代器:

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

splitstructString有一种特殊的方法:

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

按字符分割:

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

按字符串分割:

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

按关闭方式拆分:

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

14

split返回Iterator,您可以将其转换为Vec使用collectsplit_line.collect::<Vec<_>>()。通过迭代器而不是Vec直接返回a 具有多个优点:

  • split很懒。这意味着,直到您需要时,它才真正拆分线。这样,即使您只需要前几个值:split_line.take(2).collect::<Vec<_>>(),甚至只需要可以转换为整数的第一个值,也不会浪费时间分割整个字符串split_line.filter_map(|x| x.parse::<i32>().ok()).next()。最后一个示例不会浪费时间尝试处理“ 23.0”,但是一旦找到“ 1”,它将立即停止处理。
  • split不假设您要存储结果的方式。您可以使用Vec,但也可以使用任何实现的东西,FromIterator<&str>例如a LinkedList或a VecDeque或实现的任何自定义类型FromIterator<&str>

1
感谢您的详细回答,let x = line.unwrap().split(",").collect::<Vec<_>>();除非将其分为两行,否则任何想法为何都无法起作用:let x = line.unwrap();let x = x.split(",").collect::<Vec<_>>();?错误消息说:temporary value created here ^ temporary value dropped here while still borrowed
Greg

但是,如果我使用它,它将按预期工作let x = line.as_ref().unwrap().split(",").collect::<Vec<_>>();
Greg

6

还有 split_whitespace()

fn main() {
    let words: Vec<&str> = "   foo   bar\t\nbaz   ".split_whitespace().collect();
    println!("{:?}", words);
    // ["foo", "bar", "baz"] 
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.