-2

「私はテキストを検索しています」のようなフレーズと、単語のリストを含む 1 つのテキスト ファイルが与えられます。

テキストファイルに存在する単語のすべての組み合わせを見つける必要があります。

たとえば、「私は」、「私は」、「私は検索しています」、「私は検索しています」、「検索中」などの出現を検索する必要があります。

私はこれを perl で書くことを好み、より高速に動作する最適なソリューションが必要でした。

テキスト ファイルの例:

I \n
am searching \n
Text \n
searching for \n 
searching for a \n
for searching       ---> my program should not match this 
etc
4

2 に答える 2

1

以下のコードは、一致させたいすべてのsub_phrasesを出力します。

$phrase = 'I am searching for a text';
$\ = "\n";

@words = ();
print "Indices:";
while( $phrase =~ /\b\w+\b/g ) {
    push @words, {word => $&, begin => $-[0], end => $+[0]};
}

$num_words = $#words + 1;
print 'there are ', $num_words, ' words';


for( $i=0; $i<$num_words; $i++ ) {
    for( $j=$i; $j<$num_words; $j++ ) {
        ($start,$finish) = ($words[$i]->{begin}, $words[$j]->{end});
        $sub_phrase = substr $phrase, $start, $finish-$start;
        print "$i-$j: $sub_phrase";
    }
}

いくつかの説明:

  1. $\「印刷」を簡単にするためだけに
  2. $phrase-サンプルを使用
  3. @wordsは、レコードへの参照の配列です
  4. 各レコードは、単語自体を含むハッシュであり、単語の先頭にインデックスを付け、単語の最後にインデックスを付けます。
  5. 私は正規表現を持っていて、繰り返しています。単語の境界、1つ以上の単語の文字、および単語の境界を探しています。
  6. $ +と$-は、最後のREの一致のインデックス用の特別な変数です。
  7. $&は、最後のREの一致のための特別な変数です
  8. 次に、ネストされたループがあります。$ i、外側のループ変数が最初の単語です。$jが最後の単語です。それはすべての組み合わせをカバーしています。
  9. $ sub_phraseを、最初の単語の先頭から最後の単語の末尾まで計算しています。

演習を完了するには、すべてのsub_phraseを配列に保存します(「print」の代わりに「do」を@permutationsにプッシュします)。次に、テキストファイルを反復処理し、各行について、各順列との照合を試みます。

于 2012-10-25T14:53:10.083 に答える
1

これらすべてのケースで機能する式を作成できます。以下に、Perl で作成する方法を示します(ただし、目的に合わせて製品を使用することもできます)。

use List::Util qw<reduce>;

our ( $a, $b );

my $regex       
    = "\n^\n( "
    . join( "\n| "
    , @{( reduce { 
            my $r = ref( $a ) ? $a : [ "$a " ];
            my $s = $r->[0];
            [ "$b (?> [ ] $s)?", @$r ] 
        } 
        reverse split ' ', 'I am searching for a text'
        )}
    )
    . "\n)\n\\s*\n\$"
    ;
say join( "\n# ", split "\n", $regex );

# ^
# ( I (?> [ ] am (?> [ ] searching (?> [ ] for (?> [ ] a (?> [ ] text )?)?)?)?)?
# | am (?> [ ] searching (?> [ ] for (?> [ ] a (?> [ ] text )?)?)?)?
# | searching (?> [ ] for (?> [ ] a (?> [ ] text )?)?)?
# | for (?> [ ] a (?> [ ] text )?)?
# | a (?> [ ] text )?
# | text 
# )
# \s*
# $

map { say foreach m/$regex/xo } <DATA>;
  • 行全体に一致する必要があることを示したので、アンカーを追加しました。
  • 完成した正規表現にはスペースがありますが、/xそれらを無視するために使用されます。そのため、スペースを で指定します[ ]
  • グループ化表記(?>...)は非キャプチャーのバリエーションです(?:...)が、はるかに速く失敗します。http://perldoc.perl.org/perlre.html#(%3f%3epattern)を参照してください。
  • 見るList::Util::reduce
于 2012-10-25T15:10:35.103 に答える