open INP,"<C:\\Users\\hanadi\\Documents\\cs.txt";
while ($line=<INP>)
{
chomp($line);
@list=split/\s+/,$line;
foreach $w (@list)
{
$wordfreq{$w}++;
}
}
foreach $w2(keys>wordfreq)
{
print "$w2==>$wordfreq{$w}";
}
我想打印每个单词及其频率。现在我希望Perl中的代码能够跳转并打印上面的信息
排名(> 100),但不打印
每一行,每1000字只打印一行(否则会
要打印的行数太多)按频率降序排列
减少具有相同频率的单词之间的字母顺序。
答案 0 :(得分:2)
这个问题的第一个问题是定义单词“word”。我们假设您的一条评论中标点符号不是“单词”的一部分,因为您在询问如何“...从文本中删除标点符号...”
对此的一个解决方案是使用正则表达式来捕获“单词”字符,即字母数字和下划线,方法是将文本与正则表达式中的\w
进行匹配。
构建哈希,其中键是单词,关联值是计数,是要走的路。但是,在执行此操作时,您需要确保密钥完全相同,即全部为UPPER或全部为低。
在构建此哈希之后,您可以按有序值(频率)按降序对输出进行排序,并使用计数器仅打印前100个单词。将存在具有相同频率计数的单词 - 尤其是仅出现一次。你是如何想要这些打印的,因为它们是否会出现在前100名列表中会有所不同。我建议按字母顺序排列这些案例。
给出上述内容,请考虑以下解决方案,该解决方案使用以下代码上方的文本作为语料库:
use strict;
use warnings;
my %hash;
open my $fh, '<', 'words.txt' or die $!;
while (<$fh>) {
$hash{ lc $1 }++ while /(\w+)/g;
}
close $fh;
my $i = 1;
for my $word ( sort { $hash{$b} <=> $hash{$a} || $a cmp $b } keys %hash ) {
print "$i. $word: ($hash{$word})\n" if $i++ < 100 or !( $i % 1000 );
}
部分输出:
1. the: (22)
2. to: (8)
3. a: (5)
4. you: (5)
5. is: (4)
6. of: (4)
7. this: (4)
8. word: (4)
9. all: (3)
10. and: (3)
...
96. punctuation: (1)
97. punctuations: (1)
98. since: (1)
99. sort: (1)
100. suggest: (1)
限制:
在某些占有形式的单词(例如word's
)的情况下,可以看到捕获单词字符所导致的一个问题。在这种情况下,word
和s
都会被捕获为单词。如果你想保留这样的标点符号,并在空白处split
,你可以使用以下代替正则表达式行:
$hash{ lc $_ }++ for split ' ';
希望这有帮助!
答案 1 :(得分:0)
请注意所有的amons回复,并且始终rtq。 (好现场amon)。
(我已经确定)你的问题是,一旦你构造了你的wordcount哈希,你现在需要反转哈希,这样你就可以将值排序成某种顺序。这样做的问题是,多个单词可能具有相同的计数,并会覆盖先前存储的单词。
要执行此操作,您需要将数组存储在哈希值中,这是通过使用对数组的引用来完成的。散列值可能只是标量,数组不是标量,而是对数组的引用。
在重新编写您的问题时,我更新了开启和关闭调用以使用标量文件句柄,并进行适当的错误处理(或死亡),并将您的foreach语句转换为“地图”。这些可能需要一些时间来掌握,所以不要复制和粘贴它们。而是专注于反转哈希以及如何访问数组。这对你来说可能相当复杂,所以我把这些部分留在了foreach风格中。
'each'关键字从哈希中获取键/值对,并且通常以这种方式用于处理while语句中的哈希值。
你仍然需要按照amons建议和检索前100名的方法将计数转换为频率。“$ c”变量中的计数有一个线索。
#!/usr/bin/perl
# word count #wct.pl
use warnings;
use strict;
my (%wordfreq);
open my $input, '<', 'wc.txt'
or die "cannot open wc txt file $!";
map { $wordfreq{ $_ }++; } (split /\s+/, $_) while <$input> ;
close $input
or die "cannot close wc txt file $!";
# print (
# map {"$_ has ". $wordfreq{$_} . "\n" } (keys %wordfreq)
# );
foreach (keys %wordfreq){
# print "$_ has ". $wordfreq{$_} . "\n"
}
my %invertedhash;
while (my ($key,$value) = each %wordfreq){
push @{$invertedhash{$value}}, $key;
}
my $c;
foreach (reverse sort keys %invertedhash){
last if $c++ == 2;
print "words with a count of $_ are @{$invertedhash{$_}} \n";
}
exit 0;
样品
one two two
three three three four
four four four five
five five five
产生
words with a count of 4 are four five
words with a count of 3 are three
希望这有帮助。