大家好,这是我的第一个问题, 我正在使用一个名为MElt的开源程序,它将词汇解释(给出引理示例:给出 - >给出)。 MElt适用于Linux及其在Perl和Python中编程。 到目前为止,它的工作正常,但需要花费太多时间才能得出结果。 我查看了代码并找到了负责这个的循环:
while (<LEFFF>) {
chomp;
s/ /_/g;
# s/(\S)-(\S)/\1_-_\2/g;
/^(.*?)\t(.*?)\t(.*?)(\t|$)/ || next;
$form = $1; $cats = $2; $lemma = $3;
#print "$form \n";
#print "$cats \n";
#print "$lemma \n";
if ($lower_case_lemmas) {
$lemma = lc($lemma);
}
if ($it_mapping) {
next if ($form =~ /^.+'$/);
next if ($form eq "dato" && $lemma eq "datare"); # bourrin
next if ($form eq "stato" && $lemma eq "stare"); # bourrin
next if ($form eq "stata" && $lemma eq "stare"); # bourrin
next if ($form eq "parti" && $lemma eq "parto"); # bourrin
if ($cats =~ /^(parentf|parento|poncts|ponctw)$/) {$cats = "PUNCT"}
if ($cats =~ /^(PRO)$/) {$cats = "PRON"}
if ($cats =~ /^(ARTPRE)$/) {$cats = "PREDET"}
if ($cats =~ /^(VER|ASP|AUX|CAU)$/) {$cats = "VERB"}
if ($cats =~ /^(CON)$/) {$cats = "CONJ"}
if ($cats =~ /^(PRE)$/) {$cats = "PREP"}
if ($cats =~ /^(DET)$/) {$cats = "ADJ"}
if ($cats =~ /^(WH)$/) {$cats = "PRON|CONJ"}
next if ($form =~ /^(una|la|le|gli|agli|ai|al|alla|alle|col|dagli|dai|dal|dalla|dalle|degli|dei|del|della|delle|dello|nei|nel|nella|nelle|nello|sul|sulla)$/ && $cats eq "ART");
next if ($form =~ /^quest[aei]$/ && $cats eq "ADJ");
next if ($form =~ /^quest[aei]$/ && $cats eq "PRON");
next if ($form =~ /^quell[aei]$/ && $cats eq "ADJ");
next if ($form =~ /^quell[aei]$/ && $cats eq "PRON");
next if ($form =~ /^ad$/ && $cats eq "PREP");
next if ($form =~ /^[oe]d$/ && $cats eq "CONJ");
}
$qmlemma = quotemeta ($lemma);
for $cat (split /\|/, $cats) {
if (defined ($cat_form2lemma{$cat}) && defined ($cat_form2lemma{$cat}{$form}) && $cat_form2lemma{$cat}{$form} !~ /(^|\|)$qmlemma(\||$)/) {
$cat_form2lemma{$cat}{$form} .= "|$lemma";
} else {
$cat_form2lemma{$cat}{$form} = "$lemma";
$form_lemma_suffs = "@".$form."###@".$lemma;
while ($form_lemma_suffs =~ s/^(.)(.+)###\1(.+)/\2###\3/) {
if (length($2) <= 8) {
$cat_formsuff_lemmasuff2count{$cat}{$2}{$3}++;
if ($multiple_lemmas) {
$cat_formsuff_lemmasuff2count{$cat}{$2}{__ALL__}++;
}
}
}
}
}
}
变量LEFFF是由490489行组成的字典。所以循环是将这些单词与所有字典行逐一进行比较。这真的很重要。 任何想法如何优化这个? 谢谢。 MED。
答案 0 :(得分:0)
尝试将此行/^(.*?)\t(.*?)\t(.*?)(\t|$)/ || next;
更改为:
/^([^\t]++)\t([^\t]++)\t([^\t]++)(\t|$)/ || next;
对于下一个正则表达式,删除所有不需要的捕获括号。
/^(parentf|parento|poncts|ponctw)$/
到
/^parent[fo]|ponct[sw]$/ or why not /^p(?>arent[fo]|onct[sw])$/
/^(una|la|le|gli|agli|ai|al|alla|alle|col|dagli|dai|dal|dalla|dalle|degli|dei|del|della|delle|dello|nei|nel|nella|nelle|nello|sul|sulla)$/
到
/^(?>una|l[ae]|a(?>i|l(?>l[ae])?)|col|d(?>ello|[ae](?>i|l(?l[ae])?|gli))|ne(?>i|l(?>ll[aeo])?)|sul(?>la)?)$/
(注意:你可以改进这条线,通过重新排序,把最常用的决定因素/关键词放在开头)
尝试更改此行:
while ($form_lemma_suffs =~ s/^(.)(.+)###\1(.+)/\2###\3/)
通过
while ($form_lemma_suffs =~ s/^(.)([^#]++)###\1(.++)/\2###\3/)
你可以反条件:
next if ($form =~ /^quest[aei]$/ && $cats eq "ADJ");
到
next if ($cats eq "ADJ" && $form =~ /^quest[aei]$/ );
(实验性)您可以替换这两行:
next if ($form eq "stato" && $lemma eq "stare"); # bourrin
next if ($form eq "stata" && $lemma eq "stare"); # bourrin
通过
next if ($lemma eq "stare" && ($form eq "stato" || $form eq "stata"));
重要:使用perl,您可以编译正则表达式,它可以在您的情况下有用,因为您在while循环中使用相同的正则表达式。如果你这样做,不要忘记将正则表达式定义放在循环之外!例如:
my $regex = qr/^parent[fo]|ponct[sw]$/;
while (<LEFFF>) {
...
if ($cats =~ $regex) {$cats = "PUNCT"}