ChatGPT解决这个技术问题 Extra ChatGPT

如何在 Rust 中拆分字符串?

documentation,尚不清楚。在 Java 中,您可以像这样使用 split 方法:

"some string 123 ffd".split("123");
@bow 有没有办法让它成为一个字符串数组而不是一个向量?
我不知道有任何方法可以做到这一点,至少直接。您可能必须手动遍历 Split 并将其设置到数组中。当然,这意味着每个拆分中的项目数必须相同,因为数组是固定大小的,并且您必须在之前定义数组。我想这可能比简单地创建一个 Vec 更麻烦。

S
Shepmaster

使用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();

您也可以写成 .collect::<Vec<_>>()
如何获得结果的长度 - let splitsplit.len() 不存在。
@AlexanderSupertramp 使用 .count()len() 仅适用于知道其确切大小而无需消耗的迭代器,count() 消耗迭代器。
error: cannot borrow immutable local variable split` 作为可变的`
@AlexanderSupertramp let mut split,对不起。
D
DenisKolodin

有三种简单的方法:

按分隔符:s.split("separator") | s.split('/') | s.split(char::is_numeric) 通过空格:s.split_whitespace() 通过换行符:s.lines() 通过正则表达式:(使用正则表达式箱) Regex::new(r"\s").unwrap().split (“一二三”)

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

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

S
Shepmaster

有一个特殊的方法split for struct 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"]);

S
Shepmaster

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

分裂是懒惰的。这意味着它不会真正拆分线路,直到您需要它。这样,如果您只需要前几个值,就不会浪费时间拆分整个字符串:split_line.take(2).collect::>(),或者即使您只需要第一个值可以转换为整数:split_line.filter_map(|x| x.parse::().ok()).next()。最后一个示例不会浪费时间尝试处理“23.0”,但一旦找到“1”就会立即停止处理。

split 不假设您要存储结果的方式。您可以使用 Vec,但也可以使用任何实现 FromIterator<&str>,例如 LinkedList 或 VecDeque,或任何实现 FromIterator<&str> 的自定义类型。


感谢您的详细回答,任何想法为什么 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
但是,如果我使用 let x = line.as_ref().unwrap().split(",").collect::<Vec<_>>();,它会按预期工作
j
jayelm

还有split_whitespace()

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

K
Kaplan

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 = "some string "
         part2 = " ffd"

如果未找到 "☄☃🤔",则 part1 包含未触及的原始 String 并且 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);
}

进入that

任务根据字符的变化(从左到右)将(字符)字符串拆分为逗号(加上空格)分隔的字符串。