2016-01-01 9 views
9

Chcę sprawdzić, czy ciąg rozpoczyna niektórych znaków:Jaki jest poprawny i idiomatyczny sposób sprawdzenia, czy ciąg zaczyna się od określonej postaci w 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); 
} 

Użyłem char_at, ale zgłasza błąd ze względu na jego niestabilność.

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) { 
             ^~~~~~~~~~ 

obecnie używam Rust 1,5

Odpowiedz

19

Komunikat o błędzie dostarcza użytecznych wskazówek na temat tego, co należy zrobić:

często wymieniane przez chars() iterator, metoda ta może zostać usunięta lub ewentualnie przemianowany w przyszłości; zwykle jest zastąpiony przez chars/char_indices iteratorów lub dostając pierwszy char z subslice (patrz issue #27754)

  1. Mogliśmy śledzić tekst o błędzie:

    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"), 
        }; 
    } 
    

    Zauważ, że to naraża warunek błędu, którego nie obsługiwałeś! Co się stanie, jeśli nie będzie pierwszą postacią?

  2. Moglibyśmy plaster łańcuch, a następnie wzór mecz na plasterki wyrażenie:

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

    Odcinanie ciąg działa przez bajtów, a tym samym będzie to panikę, jeśli pierwszy znak nie jest dokładnie 1 bajt (również jako znak ASCII). Spowoduje również panikę, jeśli ciąg znaków jest pusty.

  3. Mogliśmy użyć metody, która jest bezpośredni mecz wyciągu problem, 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") } 
    } 
    

    Zauważ, że to rozwiązanie nie denerwuj się, jeśli ciąg jest pusta lub jeśli pierwszy znak nie jest ASCII. Prawdopodobnie wybrałbym to rozwiązanie z tych powodów. Umieszczenie ciał na tej samej linii co instrukcja if nie jest normalnym stylem rdzy, ale umieściłem to w ten sposób, aby zachować spójność z innymi przykładami. Powinieneś sprawdzić, jak wygląda podział na różne linie.


Tak na marginesie, nie trzeba collect::<Vec<_>>().iter(), to jest po prostu nieefektywny. Nie ma powodu, aby wznosić iterator, budować z niego wektor, a następnie iterować po wektorze. Po prostu użyj oryginalnego iteratora.

+0

Idealny. Dzięki! – rilut

+0

Tak, pomyślałem, że zbieranie do wektora było również nieefektywne. Nie wiedziałem, że Split to ten sam iterator co iter. Czy mogę zapytać, który jest szybszy od twoich rozwiązań? A może ich prędkość jest mniej więcej taka sama? – rilut

+1

@rilut możesz zapytać, ale nie znam odpowiedzi^_ ^. Może ktoś zadzwoni, ale możesz też przeprowadzić testy wydajności w swojej aplikacji i zobaczyć na pewno. Prawdopodobnie * zgadnę *, że wszystkie są takie same. – Shepmaster

Powiązane problemy