2

スクリプトの目的は、ファイルからすべての単語を処理し、最も多く出現するすべての単語を出力することです。したがって、それぞれ 10 回出現する 3 つの単語がある場合、プログラムはすべての単語を出力する必要があります。

ここで得たいくつかのヒントのおかげで、スクリプトが実行されるようになりました。ただし、大きなテキスト ファイル (つまり、新約聖書) は処理しません。それが私のせいなのか、コードの制限なのかはわかりません。プログラムには他にもいくつかの問題があると確信しているので、どんな助けでも大歓迎です。

#!/usr/bin/perl -w
require 5.10.0;

print "Your file: " . $ARGV[0] . "\n";
#Make sure there is only one argument
if ($#ARGV == 0){

    #Make sure the argument is actually a file
    if (-f $ARGV[0]){

        %wordHash = ();     #New hash to match words with word counts
        $file=$ARGV[0];     #Stores value of argument
        open(FILE, $file) or die "File not opened correctly.";

        #Process through each line of the file
        while (<FILE>){
            chomp;
            #Delimits on any non-alphanumeric
            @words=split(/[^a-zA-Z0-9]/,$_);
            $wordSize = @words;

            #Put all words to lowercase, removes case sensitivty
            for($x=0; $x<$wordSize; $x++){
                $words[$x]=lc($words[$x]);
            }

            #Puts each occurence of word into hash
            foreach $word(@words){
                $wordHash{$word}++;
            }
        }
        close FILE;

        #$wordHash{$b} <=> $wordHash{$a};
        $wordList="";
        $max=0;

        while (($key, $value) = each(%wordHash)){
            if($value>$max){
                $max=$value;
            }
            }

        while (($key, $value) = each(%wordHash)){
            if($value==$max && $key ne "s"){
                $wordList.=" " . $key;
            }
            }       

        #Print solution
        print "The following words occur the most (" . $max . " times): " . $wordList . "\n";
    }
    else {
        print "Error. Your argument is not a file.\n";
    }
}
else {
    print "Error. Use exactly one argument.\n";
}
4

3 に答える 3

6

問題は、スクリプトの上部にある 2 つの行が欠落していることにあります。

use strict;
use warnings;

もし彼らがそこにいたなら、彼らは次のような行をたくさん報告したでしょう:

Argument "make" isn't numeric in array element at ...

これは次の行から来ています:

$list[$_] = $wordHash{$_} for keys %wordHash;

配列要素は数値のみであり、キーは単語であるため、機能しません。ここで何が起こるかというと、任意のランダムな文字列が数値に変換され、数値で始まらない文字列は0.

あなたのコードはデータの読み取りに問題なく機能しますが、別の方法で記述します。コードが扱いにくくなるのはその後です。

私が知る限り、あなたは最も出現頻度の高い単語を出力しようとしています。その場合、次のコードを検討する必要があります。

use strict;
use warnings;

my %wordHash;
#Make sure there is only one argument
die "Only one argument allowed." unless @ARGV == 1;
while (<>) {    # Use the diamond operator to implicitly open ARGV files
    chomp;
    my @words = grep $_,           # disallow empty strings
        map lc,                    # make everything lower case
            split /[^a-zA-Z0-9]/;  # your original split
    foreach my $word (@words) {
        $wordHash{$word}++;
    }
}

for my $word (sort { $wordHash{$b} <=> $wordHash{$a} } keys %wordHash) {
    printf "%-6s %s\n", $wordHash{$word}, $word;
}

お気づきのように、ハッシュ値に基づいて並べ替えることができます。

于 2012-06-27T17:02:03.823 に答える
1

以下は、まったく異なる書き方です (「Perl は C ではない」とも言えます):

#!/usr/bin/env perl

use 5.010;
use strict; use warnings;
use autodie;

use List::Util qw(max);

my ($input_file) = @ARGV;
die "Need an input file\n" unless defined $input_file;

say "Input file = '$input_file'";

open my $input, '<', $input_file;

my %words;

while (my $line = <$input>) {
    chomp $line;

    my @tokens = map lc, grep length, split /[^A-Za-z0-9]+/, $line;
    $words{ $_ } += 1 for @tokens;
}

close $input;

my $max = max values %words;
my @argmax = sort grep { $words{$_} == $max } keys %words;

for my $word (@argmax) {
    printf "%s: %d\n", $word, $max;
}
于 2012-06-27T17:13:48.800 に答える
0

値でソートされたハッシュからキーを取得し、最初の X を抽出しないのはなぜですか?

これは例を提供するはずです:http://www.devdaily.com/perl/edu/qanda/plqa00016

于 2012-06-27T16:46:21.987 に答える