2014-09-17 2 views
0

Я закрепил несколько сценариев Perl, предназначенных для того, чтобы вытащить каждое слово из партии документов, устранить все слова остановки, остановить оставшиеся слова и создать хэш, содержащий каждое слово и его частоту появления. Однако, после работы над ним в течение нескольких минут, я получаю «Из памяти!». сообщение в окне команд. Есть ли более эффективный способ достижения желаемого результата, или мне просто нужно найти способ доступа к большему количеству памяти?Самый эффективный с точки зрения памяти способ комбинирования слов и устранения хеш-слов в Perl?

#!/usr/bin/perl 
use strict; 
use warnings; 
use Lingua::EN::StopWords qw(%StopWords); 
use Lingua::Stem qw(stem); 
use Mojo::DOM; 

my $path = "U:/Perl/risk disclosures/2006-28"; 
chdir($path) or die "Cant chdir to $path $!"; 

# This program counts the total number of unique sentences in a 10-K and enumerates the frequency  of each one. 

my @sequence; 
my %sequences; 
my $fh; 

# Opening each file and reading its contents. 
for my $file (<*.htm>) { 
    my $data = do { 
     open my $fh, '<', $file; 
     local $/; # Slurp mode 
     <$fh>; 
    }; 
    my $dom = Mojo::DOM->new($data); 
    my $text = $dom->all_text(); 
    for (split /\s+/, $text) { 
     # Here eliminating stop words. 
     while (!$StopWords{$_}) { 
      # Here retaining only the word stem. 
      my $stemmed_word = stem($_); 
      ++$sequences{"$stemmed_word"}; 
     } 
    } 
} 
+1

Я думаю, что вам нужно изменить 'в то время как (! $ StopWords {$ _}) {...} 'to' next, если определено $ StopWords {$ _}; '. Вы уже проверяете одно слово за раз с помощью 'for (split ...)', поэтому либо это слово является стоп-словом, либо нет, то нет необходимости в втором цикле. – ThisSuitIsBlackNot

+0

Да, это избавило от сообщения об ошибке «Из памяти», спасибо! – Rick

ответ

0

Если слово не %StopWords, вы входите в бесконечный цикл:

while (!$StopWords{$_}) { 
    my $stemmed_word = stem($_); 
    ++$sequences{"$stemmed_word"}; 

    # %StopWords hasn't changed, so $_ is still not in it 
} 

Там нет фактически никакой причины, чтобы использовать цикл здесь вообще. Вы уже проверяете одно слово за один раз с помощью цикла for. Слово является либо стоп-словом, либо нет, поэтому вам нужно только один раз проверить его.

Я хотел бы сделать что-то больше похож на следующее:

my $dom = Mojo::DOM->new($data); 
my @words = split ' ', $dom->all_text(); 

foreach my $word (@words) { 
    next if defined $StopWords{$word}; 

    my $stemmed_word = stem $word; 
    ++$sequences{$stemmed_word}; 
} 

В дополнении к замене внутреннего while петли с

next if defined $StopWords{$word}; 

Я также

  • удалить промежуточную $text переменных, так как кажется, что вы действительно заботитесь только о отдельных словах, нет t полный блок текста
  • добавил явную переменную цикла в for. Различные функции изменяются $_ автоматически так, чтобы избежать непреднамеренных побочных эффектов, я использую переменные явные петли для всего, кроме острот как say for @array;
  • удалены посторонних кавычек из ++$sequences{"$stemmed_word"};
+0

Я включил все ваши предложения и что часть моего кода, похоже, хорошо работает сейчас, спасибо! – Rick