2013-08-27 43 views
0

你好,每一个这是我的第一个问题在这里, 我使用了一个叫做MElt的开源程序,它引用了词(给出词法例子:give - > give)。 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。

+2

你最好在这里发表:http://codereview.stackexchange.com/ – Toto

+0

OP现已[张贴在代码审查(http://codereview.stackexchange.com/questions/30312/优化-的-A-while循环的搜索换词-IN-A-词典/ 30317)。 – amon

回答

0

尝试这条线/^(.*?)\t(.*?)\t(.*?)(\t|$)/ || next;更改为:

/^([^\t]++)\t([^\t]++)\t([^\t]++)(\t|$)/ || next; 

下一个正则表达式,删除所有uneeded捕获括号。

/^(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)?)$/

(注意:您可以改善这条线,通过重新排序,把最频繁的决定/ articolo在开始时)

尝试改变此行:

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"} 
+0

谢谢,会做。 我会告诉你 – MEd

+0

我试过了,但它仍然是一样的东西(我的意思是时间,正则表达式不再识别单词)。 我认为问题来自这样一个事实,即该程序正在比较孔490489单词与该句子的每个单词(490489 * 5单词=大约2500万次迭代)。 句子越大,花费的时间越多。 – MEd

+1

Re:'/^una | l [ae] | a(?> i | l(?> l [a ...]这实际上会减慢匹配,常量字符串的简单交替被优化为trie数据结构它允许非常快速的查找,结果类似于你写的正则表达式,但运行的开销要小得多,唯一正确的优化是删除'(...)'捕获组(通过将其更改为非捕获' (?:...)') – amon