如何在Perl中匹配两个文档之间的字符串顺序?

3
我在制作一个用于匹配两个文档中单词的PERL程序时遇到了问题。假设有文档A和B。
因此,我想删除文档A中不在文档B中的单词。 示例1
A: 我吃披萨
B: 她去市场吃披萨
结果:吃披萨 示例2
A: 吃披萨
B: 披萨吃
结果:披萨(单词顺序很重要,所以“吃”被删除。)
我使用Perl语言编写系统,并且每个文档中的句子数量不多,因此我认为不需要使用SQL。
该程序是印度尼西亚语自动论文评分的子程序。
谢谢, 如果我的问题有点混乱,请原谅。我真的很新奇 :)

你是否关心单词顺序?例如,你是否在意示例2的结果将会是两行,单词“eat”和“pizza”分别在不同的行上? - DVK
不,我已经将所有内容放在同一行上了。 - Randy
你目前进展到哪一步了?你遇到了哪个部分的困难? - Ether
请纠正我如果我错了,但是看起来你正在使用这个来确定论文之间的相似程度。 - Zaid
@Zaid:是的,但也不完全是这样,哈哈。我将比较使用LSA进行文档相似度计算的系统和使用LSA+单词顺序计算的系统,因为据我所知,LSA并不关心单词顺序(自然语言处理或类似的单词顺序)。因此,论文之间的匹配程度仍然使用LSA。 - Randy
显示剩余2条评论
1个回答

1

好的,我现在没有访问权限,所以不能保证这是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: $!";

这将创建一个新文件"A_new",其中仅包含在B中的A的单词。

这有一个小错误 - 它将用单个空格替换文件A中的任何多个空格,因此

    word1        word2              word3

将变成

word1 word2 word3

它可以被修复,但将会非常麻烦,所以我没有费心,除非您绝对需要完全正确地保留空格

解决方案 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呢?:)

你可以在shell中轻松地完成这个任务,无需使用Perl(或通过父Perl脚本中的system()调用或反引号)

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

在 Perl 中调用此函数:

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

但请看我的最后一条评论,为什么这可能被认为是“糟糕的Perl”……至少如果您在循环中执行此操作,并且迭代了非常多的文件并关心性能。


哈哈..抱歉修改了一下..这是我第一次使用Perl,有点困惑,但非常感谢您的回复.. :) - Randy
@Randy - 请看一下我在评论中的问题。你真的关心常用词汇的输出方式吗? - DVK
emm..这句话中的常用词或停用词已经被移除了,只剩下重要的词汇。 - Randy
@Randy - 好的,看看我的解决方案#2,针对Perl版本和#3的shell命令...后者更加简洁,但不是良好的Perl实践,因为它会产生两个单独的子进程,如果在循环中发生多次,则性能不佳。 - DVK
@Randy - 参加编程比赛的产物...但在这种情况下,我建议您在验证代码是否实际可行之前先保留赞美之词,因为我无法测试它 :) - DVK
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接