用于统计两个字符频率的Perl程序

时间:2017-11-11 09:34:06

标签: arrays perl sorting hash

  

我试图在文本文件中找到两个字符串,然后打印它们的频率。

#!/usr/bin/perl
#digram finder
use strict; use warnings;
#finds digrams in a file and prints them and their frequencies out

die "Must input file\n" if (@ARGV != 1);

my ($file) = @ARGV;

my %wordcount;


open (my $in, "<$file") or die "Can't open $file\n";

while (my $words = <$in>){
        chomp $words;
        my $length = length($words);
        for (my $i = 0; $i<$length; $i++){
                my $duo = substr($words, $i; 2);
                if (not exists $wordcount{$duo}){
                        $wordcount{$duo} = 1;
                }
                else {
                        $wordcount{$duo}++;
                }
        }
}

foreach my $word (sort {$wordcount{$b} cmp $wordcount{$a}} keys %wordcount){
                print "$word\t$wordcount{$duo}\n";
}


close($in);
  1. 首先,我将文本文件设置为字符串$ words。
  2. 然后,我运行for循环并在$ words
  3. 的每个位置创建一个子串$ duo
  4. 如果$ duo在hash%wordcount中不存在,那么程序会创建密钥$ duo
  5. 如果$ duo确实存在,那么该键的计数会增加1
  6. 然后程序按频率递减的顺序打印出数字及其频率
  7. 当我尝试运行代码时,我收到错误消息,我忘记在第17行声明$ word但我甚至没有字符串$ word。我不确定此错误消息来自何处。有人可以帮我找出错误的来源吗?

    谢谢

1 个答案:

答案 0 :(得分:1)

我最好的猜测是你实际上有$word而不是$words;一个错字。如果编译在文本中找到了符号$word,那么它可能就在那里。

但是,我也想对代码发表评论。清理版

while (my $words = <$in>) {
    chomp $words;
    my $last_duo_idx = length($words) - 2;
    for my $i (0 .. $last_duo_idx) {
        my $duo = substr($words, $i, 2); 
        ++$wordcount{$duo};
    }   
}

my @skeys = sort { $wordcount{$b} <=> $wordcount{$a} } keys %wordcount;

foreach my $word (@skeys) {
    print "$word\t$wordcount{$word}\n";
} 

这在一个虚构的文件上正确运行。 (我只是单独排序,以免跑掉页面。)

评论

  • 需要在该行中最后一个停止,substr0开始;因此-2

  • 几乎不需要C风格的循环

  • 此处无需测试是否存在密钥。如果它不存在则 autovivified (已创建),然后使用1递增到++;否则计数会增加。

  • 使用<=>进行数字排序,而不是cmp

  • 错别字:

    • substr($words, $i; 2)需要,而不是;,所以substr($words, $i, 2)
    • 打印中的
    • $wordcount{$duo}应为$wordcount{$word}
  • 我不确定是否命名:为什么一行文字称为$words