2017-04-09 6 views
1

私は文字列の先頭に!または!^numをスキップするアルゴリズムを実装する:Peekableイテレータを元のイテレータに戻すにはどうすればよいですか?

fn extract_common_part(a: &str) -> Option<&str> { 
    let mut it = a.chars(); 
    if it.next() != Some('!') { 
     return None; 
    } 
    let mut jt = it.clone().peekable(); 

    if jt.peek() == Some(&'^') { 
     it.next(); 
     jt.next(); 
     while jt.peek().map_or(false, |v| !v.is_whitespace()) { 
      it.next(); 
      jt.next(); 
     } 
     it.next(); 
    } 
    Some(it.as_str()) 
} 

fn main() { 
    assert_eq!(extract_common_part("!^4324 1234"), Some("1234")); 
    assert_eq!(extract_common_part("!1234"), Some("1234")); 
} 

これは動作しますが、私はCharsPeekableから復帰する方法を見つけることができないので、私はitを進めるために持っているとjtイテレータ。これにより重複したコードが発生します。

Peekableイテレータから対応するCharsイテレータに戻すにはどうすればよいでしょうか、またはこのアルゴリズムを実装するための簡単な方法がありますか?

答えて

3

要するに、あなたはできません。一般的な答えはCharsイテレータを浪費を避けるためにIterator::by_refのようなものを使用することです:

fn extract_common_part(a: &str) -> Option<&str> { 
    let mut it = a.chars(); 
    if it.next() != Some('!') { 
     return None; 
    } 

    { 
     let mut jt = it.by_ref().peekable(); 

     if jt.peek() == Some(&'^') { 
      jt.next(); 
      while jt.peek().map_or(false, |v| !v.is_whitespace()) { 
       jt.next(); 
      } 
     } 
    } 

    Some(it.as_str()) 
} 

問題は、あなたがpeekを呼び出し、それが失敗した場合、基本的なイテレータはすでにを進んでいるということです。残りの文字列を取得すると、falseをテストした文字が失われ、234が返されます。

しかし、Itertoolsにはpeeking_take_whiletake_while_refという2つの問題があります。

extern crate itertools; 

use itertools::Itertools; 

fn extract_common_part(a: &str) -> Option<&str> { 
    let mut it = a.chars(); 
    if it.next() != Some('!') { 
     return None; 
    } 

    if it.peeking_take_while(|&c| c == '^').next() == Some('^') { 
     for _ in it.peeking_take_while(|v| !v.is_whitespace()) {} 
     for _ in it.peeking_take_while(|v| v.is_whitespace()) {} 
    } 

    Some(it.as_str()) 
} 

その他のオプションが含まれます:

  • 文字列を超える増分事前のこの種のために設計されてstrcursorのような木枠を使用します。
  • 通常の文字列で直接構文解析を行い、オプティマイザが冗長な境界チェックを排除することを望みます。
  • あなたは結果にのみ関心がある場合は、検証せずに、
+0

5秒。 "新しい答え"の通知を受け取っていない。 :P –

+1

@DK。さて、私は答えなかった部分を盗んでしまいます。どうすれば作者の免責事項を書く必要がないので、より合法的に見えるでしょう;-) – Shepmaster

+2

**免責事項**:Shepmasterは 'strcursor'の著者から' strcursor'の提案を受けました。それは推奨としてではなく例としてとらえられるべきです。 –

1

正規表現や他の解析ライブラリを使用します。

fn extract_common_part(a: &str) -> Option<&str> { 
    a.chars().rev().position(|v| v.is_whitespace() || v == '!') 
     .map(|pos| &a[a.len() - pos..])  
} 

fn main() { 
    assert_eq!(extract_common_part("!^4324 1234"), Some("1234")); 
    assert_eq!(extract_common_part("!1234"), Some("1234")); 
} 
関連する問題