Rust で文字列が特定の文字で始まるかどうかを確認する正しい慣用的な方法は何ですか? 質問する

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

エラー メッセージには、対処方法に関する役立つヒントが表示されます。

このメソッドはイテレータに置き換えられることが多いためchars()、将来的には削除されるか、名前が変更される可能性があります。通常はchars/char_indicesイテレータに置き換えられるか、サブスライスから最初の文字を取得することで置き換えられます (問題 #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 バイト (つまり ASCII 文字) でない場合はパニックになります。文字列が空の場合もパニックになります。これらのパニックを回避するには、次の操作を行います。

    for line in lines_of_text.split("\n") {
        match line.get(..1) {
            Some("#") => println!("Heading"),
            Some(">") => println!("Quotation"),
            Some("-") => println!("Inline list"),
            Some("`") => println!("Code"),
            _ => println!("Other"),
        };
    }
    
  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 スタイルではありませんが、他の例との一貫性を保つためにそのようにしました。それらを別の行に分割するとどのように見えるかを確認してください。


余談ですが、 は必要ありませんcollect::<Vec<_>>().iter()。これは非効率的です。反復子を取得して、そこからベクトルを構築し、そのベクトルを反復処理する理由はありません。元の反復子を使用してください。

おすすめ記事