Исправление ошибок Perl, когда я пытаюсь передать хеш (по ссылке) И переменную в сабвуфер, чтобы вывести соответствующее значение в хеш - PullRequest
0 голосов
/ 14 февраля 2019

Я ломаю голову над задачей Perl в моем курсе по обработке естественного языка, который нам поручено решать.

То, что они требуют, чтобы мы могли решать с помощью Perl, таково:

  • Ввод: программа получает два ввода из стандартного ввода в форме и типе;perl program.pl

  • Обработка и вывод:

    Часть 1: программа разбивает слова на слова в filename.txt и сохраняет эти слова в хэше с частотой их появления

    Часть 2: программа использует ввод для целей хеширования.Если слово не может быть найдено в хэше (то есть в тексте), выводится ноль в качестве частоты слова.Если слово МОЖЕТ быть действительно найдено в хэше, распечатывает соответствующее значение частоты слова в хэше.

Из опыта я уверен, что мой сценарий уже способен делать "Часть 1 », указанная выше.

Часть 2 должна быть выполнена с использованием подпрограммы Perl (подпрограммы), которая принимает хэш по ссылке вместе с хешем для.Это была часть, с которой у меня были серьезные проблемы.

Первая версия до серьезных изменений, предложенных Стефаном Беккером;

#!/usr/bin/perl                                                                           

use warnings;
use strict;

sub hash_4Frequency
{
    my ($hashWord, $ref2_Hash) = @_;                       
    print $ref2_Hash -> {$hashWord}, "\n";  # thank you Stefan Becker, for sobriety
}

my %f = ();  # hash that will contain words and their frequencies                              
my $wc = 0;  # word-count                                       

my ($stdin, $word_2Hash) = @ARGV;  # corrected, thanks to Silvar

while ($stdin)
{
    while ("/\w+/")
    {
        my $w = $&;
        $_ = $";
        $f{lc $w} += 1;
        $wc++;
    }
}

my @args = ($word_2Hash, %f);
hash_4Frequency(@args);

Вторая версия после некоторых изменений;

#!/usr/bin/perl

use warnings;
use strict;

sub hash_4Frequency
{
    my $ref2_Hash = %_;
    my $hashWord = $_;

    print $ref2_Hash -> {$hashWord}, "\n";
}

my %f = ();  # hash that will contain words and their frequencies
my $wc = 0;  # word-count

while (<STDIN>) 
{
    while (/\w+/)
    {
        chomp;
        my $w = $&;
        $_ = $";

        $f{$_}++ foreach keys %f;
        $wc++;
    }
}

hash_4Frequency($_, \%f);

Когда я выполняю «./script.pl

 Use of uninitialized value $hashWord in hash element at   
 ./word_counter2.pl line 35.

 Use of uninitialized value in print at ./word_counter2.pl line 35.

На что Perl жалуется для второй версии;

 Can't use string ("0") as a HASH ref while "strict refs" in use at ./word_counter2.pl line 13, <STDIN> line 8390.

По крайней мере, теперь я знаю, что сценарий может успешно работать до этого самого последнего момента, и он кажется чем-то семантическим, а не синтаксическим.

Есть еще какие-нибудь советы по этой последней части?Был бы очень признателен.

PS: Извините, паломники, я просто новичок на пути Perl.

Ответы [ 2 ]

0 голосов
/ 14 февраля 2019

Ваша исправленная версия не намного лучше, чем ваша первая.Хотя он проходит проверку синтаксиса, он имеет несколько семантических ошибок.Вот версия с минимальным количеством исправлений, чтобы она работала

ПРИМЕЧАНИЕ: это не то, как вы пишете в идиоматическом Perl.

#!/usr/bin/perl
use warnings;
use strict;

sub hash_4Frequency($$) {
    my($ref2_Hash, $hashWord) = @_;

    print $ref2_Hash -> {$hashWord}, "\n";
}

my %f = ();  # hash that will contain words and their frequencies
my $wc = 0;  # word-count

while (<STDIN>)
{
    chomp;
    while (/(\w+)/g)
    {
        $f{$1}++;
        $wc++;
    }
}

hash_4Frequency(\%f, $ARGV[0]);

Тестовый выводс "Lorem ipsum" в качестве входного текста:

$ cat dummy.txt 
Lorem ipsum dolor sit amet, consectetur adipisici elit, sed eiusmod tempor
incidunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis
nostrud exercitation ullamco laboris nisi ut aliquid ex ea commodi consequat.
Quis aute iure reprehenderit in voluptate velit esse cillum dolore eu fugiat
nulla pariatur. Excepteur sint obcaecat cupiditat non proident, sunt in culpa
qui officia deserunt mollit anim id est laborum.

$ perl <dummy.txt dummy.pl Lorem
1

КОД БОНУСА: это будет мой первый удар по данной проблеме.Ваша первая версия содержит все слова в нижнем регистре, что имеет смысл, поэтому я сохранил ее:

#!/usr/bin/perl
use warnings;
use strict;

sub word_frequency($$) {
    my($hash_ref, $word) = @_;

    print "The word '${word}' appears ", $hash_ref->{$word} // 0, " time(s) in the input text.\n";
}

my %words;  # hash that will contain words and their frequencies
my $wc = 0; # word-count

while (<STDIN>) {
    # lower case all words
    $wc += map { $words{lc($_)}++ } /(\w+)/g
}

print "Input text has ${wc} words in total, of which ",
      scalar(keys %words),
      " are unique.\n";

# return frequency in input text for every word on the command line
foreach my $word (@ARGV) {
    word_frequency(\%words, lc($word));
}

exit 0;

Тестовый прогон

$ perl <dummy.txt dummy.pl Lorem ipsum dolor in test
Input text has 66 words in total, of which 61 are unique.
The word 'lorem' appears 1 time(s) in the input text.
The word 'ipsum' appears 1 time(s) in the input text.
The word 'dolor' appears 1 time(s) in the input text.
The word 'in' appears 2 time(s) in the input text.
The word 'test' appears 0 time(s) in the input text.
0 голосов
/ 14 февраля 2019

Быстрый тест в командной строке с этим примером показывает один правильный синтаксис для передачи слова и хэш-ссылку на функцию:

use strict;
use warnings;
use v5.18;
sub foo {
    my $word = $_[0];
    shift;
    my $hsh = $_[0];
    say $word; say $hsh->{$word};
};
foo("x", {"x" => 4});
# prints x and 4

Это обрабатывает список аргументов как массив, получаяпервый элемент и высовывать его каждый раз.Вместо этого я бы фактически предложил получить оба аргумента одновременно: my ($word, $hsh) = @_;

И ваш синтаксис для доступа к элементам хеш-ссылки вполне может быть правильным, но я считаю, что проще запомнить синтаксис, который разделяется междуC ++ и perl: стрелка означает разыменование.Кроме того, вы знаете, что никогда не будете случайно копировать структуру данных при использовании синтаксиса стрелки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...