Perl で 2 つのドキュメント間で文字列の順序を一致させるにはどうすればよいですか?

StackOverflow https://stackoverflow.com/questions/2894213

  •  04-10-2019
  •  | 
  •  

質問

2 つの文書内の単語を照合する PERL プログラムを作成する際に問題があります。文書AとBがあるとします。

そこで、文書 A にある、文書 B にはない単語を削除したいと思います。

例1:

答え:私はピザを食べる

B:彼女は市場に行ってピザを食べます

結果:ピザを食べる

例2:答え:ピザを食べる

B:ピザを食べる

結果:ピザ(単語の注文は関連性があるため、「Eat」が削除されます。)

システムには Perl を使用していますが、各ドキュメントの文量はそれほど多くないので SQL は使用しないと思います

このプログラムは、インドネシア語 (バハサ語) の自動エッセイ採点用のサブプログラムです。

ありがとう、私の質問が少し混乱しているなら申し訳ありません。私は「この世界」については本当に初心者です:)

役に立ちましたか?

解決

OK、現時点ではアクセス権がないため、これが 100% であるか、コンパイルされるかどうかさえ保証されていませんが、十分なガイダンスは提供されるはずです。

解決策 1:(語順は関係ありません)

#!/usr/bin/perl -w

use strict;
use File::Slurp;

my @B_lines = File::Slurp::read_file("B") || die "Error reading B: $!";
my %B_words = ();
foreach my $line (@B_lines) {
    map { $B_words{$_} = 1 } split(/\s+/, $line);
}
my @A_lines = File::Slurp::read_file("A") || die "Error reading A: $!";
my @new_lines = ();
foreach my $line (@A_lines) {
    my @B_words_only = grep { $B_words{$_} } split(/\s+/, $line);
    push @new_lines, join(" ", @B_words_only) . "\n";
}
File::Slurp::write_file("A_new", @new_lines) || die "Error writing A_new: $!";

これにより、B に含まれる A の単語のみを含む新しいファイル「A_new」が作成されます。

これにはわずかなバグがあります。ファイル A 内の複数の空白は単一の空白に置き換えられます。

    word1        word2              word3

となります

word1 word2 word3

これは修正できますが、修正するのは非常に面倒なので、空白を 100% 正しく保持することが絶対に必要な場合を除き、気にしませんでした。

解決策 2:(語順は重要ですが、空白の保持をまったく考慮せずにファイル A から単語を出力できます)

#!/usr/bin/perl -w

use strict;
use File::Slurp;

my @A_words = split(/\s+/gs, File::Slurp::read_file("A") || die "Error reading A:$!");
my @B_words = split(/\s+/gs, File::Slurp::read_file("B") || die "Error reading B:$!");
my $B_counter = 0;
for (my $A_counter = 0; $A_counter < scalar(@A_words); ++$A_counter) {
    while ($B_counter < scalar(@B_words)
        && $B_words[$B_counter] ne $A_words[$A_counter]) {++$B_counter;}
    last if $B_counter == scalar(@B_words);
    print "$A_words[$A_counter]";
}

解決策 3 (なぜまた Perl が必要なのでしょうか?:))

これは、Perl を使用せずにシェルで簡単に実行できます (または、親 Perl スクリプトの system() 呼び出しまたはバッククォートを介して)。

comm -12 A B | tr "\012" " " 

これを Perl から呼び出すには:

my $new_text = `comm -12 A B | tr "\012" " " `;

しかし、これが「悪い Perl」とみなされる理由については、私の最後のコメントを参照してください...少なくとも、非常に多くのファイルが反復されるループでこれを実行し、パフォーマンスを重視する場合には。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top