2011-05-19 18 views
3

別の文字列yの文字列xを正規表現で検索する必要がありますが、次にその文字列のトークン(単語)インデックスを知る必要があります他の正規表現(例えば空白)を使って文字列yをトークン化(分割)した後のヒットの最初の文字。最初の正規表現では部分文字列が見つかる可能性があるので、トークン(単語)の先頭に停止することは保証できません。正規表現文字列検索の後でトークン(単語)インデックスを効率的に見つける方法

これを実装する最適なアルゴリズムは何でしょうか。単純なアプローチは、以下のようになります。

  • 第二の正規表現を使用して要素のアレイに第一の正規表現と文字オフセットを取得Z
  • スプリットYを用いて、yのxに対する

    1. 検索ループを各要素の長さを変数LENGTHに加算してカウンタに1を加算するカウンタ
    2. LENGTHがz以上のときにループを停止する
    3. ヒットの最初の文字のトークンのインデックスCOUNTER
    4. の値になります

    (これは、分割関数が分割文字を格納することを前提としています。空白)を配列要素としているため、非常に無駄である。

    具体的な例(単純な例):「月がチーズでできている」という文字列の検索「ade」のトークン(単語)インデックスを知りたいとします。この関数は私に答えを返します:3(インデックス配列がゼロの場合)

    ==編集==
    アルゴリズムはまた、正規表現検索はトークンの境界を越えたときに動作する必要があります。たとえば、「月がチーズで作られている」の「de of ch」を検索するときには、再びインデックス「3」を返します。あなたの更新情報によると

  • 答えて

    1

    #!/usr/bin/perl -l 
    use strict; 
    use warnings; 
    
    my $string = "The moon is made of cheese"; 
    my $search = 'de of ch'; 
    my $pos = index($string, $search); 
    if ($pos != -1) { 
        my $substr = substr($string, 0, $pos); 
        my @words = split /\s+/, $substr; 
        print "found in word #", $#words, "\n"; 
    } else { 
        print "not found\n"; 
    } 
    

    出力:文字列の最初のパターンのための

    found in word #3 
    
    +0

    ニースの一例が、正規表現の検索がトークン内にある場合にのみ動作します。私はそれがそうでないかもしれないことを強調するために質問を編集しました。 – Lozzer

    +0

    @Lozzer:最新の回答をご覧ください。 – Toto

    +0

    非常に良い!これは確かに、質問の単純なアプローチよりもずっと効率的です。ありがとうございました。 – Lozzer

    1

    見て、その後、一部に第2のパターン文字列の出現回数を数えます最初のパターンの前にある文字列のここで

    は仕事をしているperlスクリプトです:

    #!/bin/perl -w 
    
        my $string = 'The moon is made of cheese'; 
        my $lookedfor = 'de of che'; 
        my $separator = q/\W+/; 
    
        my $count = undef; 
        if ($string =~ /(.*?)$lookedfor/) { 
         # Keep the smallest (.*?) part of string before the match. 
         my $firstpart = $1; 
    
         $count = 0; 
         # Count the number of separator 
         $count++ while $firstpart =~ m/$separator/g; 
        } 
    
        if (defined $count) { 
         printf "index of '%s' in '%s' is %d\n", $lookedfor, $string, $count; 
        } else { 
         printf "No occurence of '%s' in '%s'\n", $lookedfor, $string; 
        } 
    
    +0

    これは確かに仕事をし、質問の簡単な方法よりもはるかに優れています。しかし、M42のアプローチはさらにエレガントです。私は受け入れられた答えとして彼をマークするつもりです。 – Lozzer

    +0

    あなたは私の答えが気に入ってうれしいです。 M42のアプローチでは、質問で必要に応じて「文字列xの正規表現検索を実行しない」「インデックス」を使用します。私は分割部分が非常に効率的であることに同意します。 – dchoulette

    +0

    私はM42のアプローチが 'index'を使用していることに同意しますが、これを正規表現に変更して$ pos値を得るのは簡単です。 – Lozzer

    関連する問題