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

时间:2016-01-01 20:13:41

标签: 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);
}

我使用了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) {
                                      ^~~~~~~~~~

我目前正在使用Rust 1.5

1 个答案:

答案 0 :(得分:20)

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

  

经常被chars()迭代器替换,此方法可能会被删除或可能在将来重命名;它通常由chars / char_indices迭代器替换,或者从子切片中获取第一个char(参见issue #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"),
        };
    }
    

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

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

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

    对字符串进行切片操作按字节,因此如果您的第一个字符不完全是1个字节(a.k.a.是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") }
    }
    

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

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