检查字符串是否以Rust中的某个字符开头的正确和惯用方法是什么?

ril*_*lut 11 string rust

我想检查字符串是否以某些字符开头:

for line in lines_of_text.split("\n").collect::<Vec<_>>().iter() {
    let rendered = match line.char_at(0) {
        '#' => {
            // Heading
            Cyan.paint(*line).to_string()
        }
        '>' => {
            // Quotation
            White.paint(*line).to_string()
        }
        '-' => {
            // Inline list
            Green.paint(*line).to_string()
        }
        '`' => {
            // Code
            White.paint(*line).to_string()
        }
        _ => (*line).to_string(),
    };
    println!("{:?}", rendered);
}
Run Code Online (Sandbox Code Playgroud)

我已经习惯了char_at,但由于其不稳定性而报告错误.

main.rs:49:29: 49:39 error: use of unstable library feature 'str_char': frequently replaced by the chars() iterator, this method may be removed or possibly renamed in the future; it is normally replaced by chars/char_indices iterators or by getting the first char from a subslice (see issue #27754)
main.rs:49      let rendered = match line.char_at(0) {
                                      ^~~~~~~~~~
Run Code Online (Sandbox Code Playgroud)

我目前正在使用Rust 1.5

She*_*ter 23

该错误消息提供了有关如何操作的有用提示:

通常由chars()迭代器替换,此方法可能会被删除或可能在将来重命名; 它通常由chars/ char_indicesiterators 替换或通过从子切片获取第一个char(请参阅问题#27754)

  1. 我们可以按照错误文字:

    for line in lines_of_text.split("\n") {
        match line.chars().next() {
            Some('#') => println!("Heading"),
            Some('>') => println!("Quotation"),
            Some('-') => println!("Inline list"),
            Some('`') => println!("Code"),
            Some(_)   => println!("Other"),
            None      => println!("Empty string"),
        };
    }
    
    Run Code Online (Sandbox Code Playgroud)

    请注意,这会暴露您未处理的错误情况!如果没有第一个角色怎么办?

  2. 我们可以切割字符串,然后在字符串切片上进行模式匹配:

    for line in lines_of_text.split("\n") {
        match &line[..1] {
            "#" => println!("Heading"),
            ">" => println!("Quotation"),
            "-" => println!("Inline list"),
            "`" => println!("Code"),
            _   => println!("Other")
        };
    }
    
    Run Code Online (Sandbox Code Playgroud)

    切片字符串按字节操作,因此如果您的第一个字符不是1字节(也就是ASCII字符),这将会出现混乱.如果字符串为空,它也会发生混乱.

  3. 我们可以使用与您的问题陈述直接匹配的方法str::starts_with:

    for line in lines_of_text.split("\n") {
        if line.starts_with('#')      { println!("Heading") }
        else if line.starts_with('>') { println!("Quotation") }
        else if line.starts_with('-') { println!("Inline list") }
        else if line.starts_with('`') { println!("Code") }
        else                          { println!("Other") }
    }
    
    Run Code Online (Sandbox Code Playgroud)

    请注意,如果字符串为空或第一个字符不是ASCII,则此解决方案不会发生混乱.出于这些原因,我可能会选择这个解决方案.将if主体放在与if语句相同的行上并不是正常的Rust样式,但我这样做是为了让它与其他示例保持一致.你应该看看如何将它们分成不同的线条.


顺便说一句,你不需要collect::<Vec<_>>().iter(),这只是效率低下.没有理由采用迭代器,从中构建一个向量,然后迭代向量.只需使用原始迭代器.

  • @rilut它在任何方面都不是*相同的*迭代器,但它是*迭代器*都是一样的. (2认同)