gpt4 book ai didi

perl - 如何使用perl删除计算频率计算中的原始字符串

转载 作者:行者123 更新时间:2023-12-01 09:17:23 27 4
gpt4 key购买 nike

我在计算使用 Perl 从文本文件中读取的字符串列表的频率时遇到问题。我想要做的是,分别计算每行中的字符数。我的代码确实可以使用它,但它也将原始字符串计算为单个字符。

这是我的代码,

sub cal_frequency{
while (my @row = <$fd>){
chomp;
for (my $i=0; $i<=147; $i++){
my %count;
print "$row[$i]\n";
foreach my $str (split //, $row[$i]) {
$count{$str}++;
}
foreach my $str (sort keys %count) {
printf "%-31s %s\n", $str, $count{$str} ;
}
}
}
}

这是我得到的输出。

HMHHMSHHHNHHMEHFFHHHHHHHDHDE
1
D 2
E 2
F 2
H 17
M 3
N 1
S 1
LLLWLFLLWLWLLWWLLLLFLLLLWLFW
1
F 3
L 18
W 7
TTTTTDTTTTTTTTTTSTTTTSSTTATT
1
A 1
D 1
...
...
...

有没有人可以帮我弄清楚代码有什么问题。

最佳答案

您选择了错误的变量。您正在将输入读入 @row,但随后您只需调用 chomp; 而不带参数。那个 chomps $_,而不是 @row

while (my @row = <$fd>){
chomp @row;
# ...

你本可以自己发现的。如果您为每个输入行输出 %count 的实际内容,您会看到有一个换行符 \n 被计算一次。所以你看到的第一行

HMHHMSHHHNHHMEHFFHHHHHHHDHDE
1

实际上不是完整的字符串。它是字符串末尾的换行符。试试这个。我建议您将迭代变量更改为仅执行一行,这样您就不会被输出淹没。

for ( my $i = 0; $i <= 1; $i++ ) {

# ...
foreach my $str ( sort keys %count ) {
printf "%-31s %s\n", $str, $count{$str};
}
use Data::Dumper;
print Dumper \%count;
}

你现在会看到这个:

$VAR1 = {
'A' => 1,
'S' => 3,
'T' => 23,
'
' => 1,

还有换行符。


您的代码有点奇怪。你做了很多不必要的事情。我将尝试为您解释它们以简化您的代码。

您的 while 循环只运行一次,因为您将整个文件一次性放入 @row 中。

sub cal_frequency {
while ( my @row = <DATA> ) {
print "while iteration\n";

我从这里的输出中省略了 printf

while iteration
HMHHMSHHHNHHMEHFFHHHHHHHDHDE
LLLWLFLLWLWLLWWLLLLFLLLLWLFW
TTTTTDTTTTTTTTTTSTTTTSSTTATT

如您所见,只有一个 while 迭代。如果你有一个很长的文件,那么逐行阅读会更明智。

while ( my $row = <DATA> ) {
chomp $row;
# ...
}

一旦你这样做了,你的 C 风格 for 循环就会过时。实际上,该循环将程序与输入耦合,因为您在那里硬编码了输入的行数。如果没有这个循环,程序可以处理任意长的文件(就像你展示给我们的和我正在使用的那三行)。

尽可能晚地声明变量并尽可能靠近您需要它们的位置也是一种很好的方式。我已移动 my %count 并更改了缩进。

sub cal_frequency {
while ( my $row = <DATA> ) {
chomp $row;
print "$row\n";

my %count;
foreach my $str ( split //, $row ) {
$count{$str}++;
}
foreach my $str ( sort keys %count ) {
printf "%-31s %s\n", $str, $count{$str};
}
}
}

现在更清楚发生了什么。

在您的代码中,您使用的是词法文件句柄。那太棒了。但它似乎是在子程序之外创建的。最好将其作为参数传递。

最后,在您的两个 foreach 循环中选择变量名 $str 令人困惑。当我看到 string 时,我会想到单词或其他很长的东西。但是在这里你特别想把你的字符串(行)分解成字符。那是长度为 1 的字符串。所以给他们命名。

这是最后的程序。

use strict;
use warnings;

sub cal_frequency {
my ($fh) = @_;

while ( my $row = <$fh> ) {
chomp $row;
print "$row\n";

my %count;
foreach my $chr ( split //, $row ) {
$count{$chr}++;
}
foreach my $chr ( sort keys %count ) {
printf "%-31s %s\n", $chr, $count{$chr};
}
}
}

cal_frequency(\*DATA);

__DATA__
HMHHMSHHHNHHMEHFFHHHHHHHDHDE
LLLWLFLLWLWLLWWLLLLFLLLLWLFW
TTTTTDTTTTTTTTTTSTTTTSSTTATT

还有输出。

HMHHMSHHHNHHMEHFFHHHHHHHDHDE
D 2
E 2
F 2
H 17
M 3
N 1
S 1
LLLWLFLLWLWLLWWLLLLFLLLLWLFW
F 3
L 18
W 7
TTTTTDTTTTTTTTTTSTTTTSSTTATT
A 1
D 1
S 3
T 23

关于perl - 如何使用perl删除计算频率计算中的原始字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40738837/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com