使用perl查找字符串中唯一单词的最高频率

时间:2015-11-16 09:47:01

标签: perl

我正在编写脚本来获取和打印段落中最高频率的独特单词。

有关代码 - 请参阅附件。

my $freq; 
my $word; 
my $textdata = <<"END_MSG"; 
mm mm mm mm kk kk kk kkkk kk To pp pp pp pp pp pp. 
END_MSG

foreach $word ( split ( ' ', lc $textdata) 
{
    $freq{$word}++;
    #print $freq{$word};
    #print "..";
}

use sort 'stable';
my @listing = ( sort { $freq{$b} <=> $freq{$a} } keys %freq)[0..5];
foreach my $word ( @listing ) 
{
    print $freq{$word}." $word\n";
};

输出1:

5 pp
4 mm
4 kk
1 pp.
1 to
1 kkkk

输出2:

5 pp
4 kk
4 mm
1 pp.
1 to
1 kkkk

单词mmkk的频率为4 - 但每当订单变化时我正在运行。

我希望输出保持不变。

我如何根据情况进行排序?

关心, 拉姆。

1 个答案:

答案 0 :(得分:3)

是的,这里的问题是 - 你试图对两个没有相对排序的值进行排序。

因此,您的结果基于keys的退货订单,按定义随机(ish)。就sort而言,这两者是等价的,因此它们出现的方式无关紧要。

如果多次运行keys %freq,您将获得不同的关键订单。因为有时kk会在mm之前出现 - 因为就sort而言,它们是相同的,因为它们具有相同的频率 - 这就是为什么你得到你做的。

所以你需要的是一个二级排序,这是一致的。比如 - 例如 - 按字母顺序排序如果频率相同。

有用 - 我们可以使用<=>||运算符相结合的事实让您链接条件。因为如果你这样做;

 $condition1 || $condition2;

如果为“true”则返回条件1 - 如果为假则返回条件2。 <=>会返回10-1。这里只有0为false,所以你可以这样做:

 $a <=> $b || $a cmp $b

或者在你的情况下:

$freq{$b} <=> $freq{$a} || $a cmp $b

像这样:

#!/usr/bin/env perl
use strict;
use warnings;
use Data::Dumper;

my @words = qw ( mm mm mm mm kk kk kk kkkk kk To pp pp pp pp pp pp nn nn ); 
my %freq;
$freq{$_}++ for @words; 
print Dumper \%freq; 

foreach my $word ( sort { $freq{$b} <=> $freq{$a} 
                       ||        $a cmp $b        } keys %freq ) { 
    print "$word => $freq{$word}\n";
}

这将首先对频率进行排序,如果有两个具有相同频率的将按字母数字排序。因此,在kk => 4之前mm => 4 始终总是

您还应该在代码中注明:

  • 你没有声明%freq - 你应该这样做。您还应该启用use strict;use warnings;,这会告诉您这一点。

  • use sort 'stable';似乎没有做任何事情。这并不奇怪,因为sort工作得很好。