如何在Rust中拆分字符串?

354

文档中看不出来。在Java中,您可以使用split方法,例如:

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

2
https://doc.rust-lang.org/std/string/struct.String.html - Dulguun Otgon
@bow 有没有办法将它变成字符串数组而不是向量? - Greg
我并不知道有直接的方法来完成这个操作。你可能需要手动迭代Split并将其设置到数组中。当然,这意味着每个Split中的项目数量必须相同,因为数组是固定大小的,并且您必须在之前定义好数组。我想这可能比创建一个Vec更麻烦。 - bow
7个回答

412

使用split()函数

let parts = "some string 123 content".split("123");

这将返回一个迭代器,您可以循环遍历,或者使用collect()方法转换为向量。例如:

for part in parts {
    println!("{}", part)
}

或者:

let collection = parts.collect::<Vec<&str>>();
dbg!(collection);

或者:

let collection: Vec<&str> = parts.collect();
dbg!(collection);

44
你也可以写成.collect::<Vec<_>>() - Chris Morgan
2
如何获取结果“let split”的长度?“split.len()”不存在。 - Incerteza
13
使用.count()方法。len()方法只适用于可以在不需要被消耗的情况下知道其确切大小的迭代器,而count()方法会消耗迭代器。 - Manishearth
1
错误:无法将不可变本地变量split作为可变的借用 - Incerteza
2
@AlexanderSupertramp 抱歉,应该是 let mut split - Manishearth
显示剩余5条评论

201

有三种简单的方式:

  1. By separator:

     s.split("separator")  |  s.split('/')  |  s.split(char::is_numeric)
    
  2. By whitespace:

     s.split_whitespace()
    
  3. By newlines:

     s.lines()
    
  4. By regex: (using regex crate)

     Regex::new(r"\s").unwrap().split("one two three")
    
每种类型的结果都是一个迭代器:
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());

59
有一种特殊的方法split用于结构String
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"]);

39
split返回一个Iterator,您可以使用collect将其转换为Vecsplit_line.collect::<Vec<_>>()。通过迭代器而不是直接返回Vec具有以下几个优点:
  • split是惰性的。这意味着它只会在需要时才真正地分割该行。如果您只需要前几个值,则不会浪费时间分割整个字符串:split_line.take(2).collect::<Vec<_>>(),或者如果您只需要可以转换为整数的第一个值:split_line.filter_map(|x| x.parse::<i32>().ok()).next()。此最后一个示例不会浪费时间尝试处理“23.0”,但一旦找到“1”,它就会立即停止处理。
  • split不对存储结果的方式做出任何假设。您可以使用Vec,但也可以使用任何实现FromIterator<&str>的东西,例如LinkedListVecDeque,或任何实现FromIterator<&str>的自定义类型。

2
感谢您详细的回答,您有什么想法为什么 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
1
然而,如果我使用 let x = line.as_ref().unwrap().split(",").collect::<Vec<_>>();,它会按预期工作。 - Greg

15

还有split_whitespace()方法,它与字符串分割有关。

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

6
如果您正在寻找Python风格的拆分方式,其中您可以将拆分字符串的两端进行元组解包,则可以执行以下操作:
if let Some((a, b)) = line.split_once(' ') {
    // ...
}

不错的补充,有关 https://dev59.com/e1gR5IYBdhLWcg3wRbk1 - Code4R7

3

这位OP的问题是如何使用多字符字符串进行拆分,以下是一种获取part1part2结果的方法,以String形式存储在vector中。
在这里,我们使用非ASCII字符字符串"☄☃"代替"123"进行拆分:

let s = "☄☃";  // also works with non-ASCII characters
let mut part1 = "some string ☄☃ ffd".to_string();
let _t;
let part2;
if let Some(idx) = part1.find(s) {
    part2 = part1.split_off(idx + s.len());
    _t = part1.split_off(idx);
}
else {
    part2 = "".to_string();
}    

获取: part1 = "一些字符串 "
         part2 = " ffd"

如果未找到"☄☃",则part1包含未更改的原始字符串,而part2为空。


这里有一个在Rosetta Code中的好例子 - 基于字符变化拆分字符字符串 - 您可以将使用split_off的简短解决方案转换为漂亮的示例:

fn main() {
    let mut part1 = "gHHH5YY++///\\".to_string();
    if let Some(mut last) = part1.chars().next() {
        let mut pos = 0;
        while let Some(c) = part1.chars().find(|&c| {if c != last {true} else {pos += c.len_utf8(); false}}) {
            let part2 = part1.split_off(pos);
            print!("{}, ", part1);
            part1 = part2;
            last = c;
            pos = 0;
        }
    }
    println!("{}", part1);
}

将一个(字符)字符串按字符的变化(从左到右)拆分为逗号(加一个空格)分隔的字符串。请见这个链接

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接