【问题标题】:Print min and max of a hash value in Perl with corresponding key在 Perl 中使用相应的键打印哈希值的最小值和最大值
【发布时间】:2018-07-04 21:01:50
【问题描述】:

我是 Perl 的新手(我也会说一般的编程),我正在尝试用我为学校作业做的 perl 脚本解决一个简单的问题。我不应该使用任何模块,我认为他们不会接受它,因为我必须先学会如何做事。

我被要求创建一个 html 输入表单来输入学生的姓名和分数,并将它们传递给我的 perl 脚本并计算每个学生的 GPA,到目前为止一切正常。

然后我应该将这些信息保存在哈希中,并获取 GPA 最高的学生姓名,然后是最低的学生姓名,但没有任何效果。

首先,我在任何函数之外定义了每个 GPA,以便我的每个子例程都可以读取,然后我尝试为每个学生指定他的 GPA,但我不确定我这样做是否正确。

my $cgi = CGI -> new();

my @name = $cgi->param('name');

my $gpa_one;
my $gpa_two;
my $gpa_three;
my $gpa_four;
my $gpa_five;
my $gpa_six;
my $gpa_seven;
my $gpa_eight;
my $gpa_nine;
my $gpa_ten;

my %stud_gpa = (
$name[0] => $gpa_one,
$name[1] => $gpa_two,
$name[2] => $gpa_three,
$name[3] => $gpa_four,
$name[4] => $gpa_five,
$name[5] => $gpa_six,
$name[6] => $gpa_seven,
$name[7] => $gpa_eight,
$name[8] => $gpa_nine,
$name[9] => $gpa_ten,
);

每个 GPA 都是子程序的结果。

我一直在尝试以多种方式对 GPA 进行排序(对哈希进行排序,只是尝试将它们中的每一个分配给一个简单的数组并对数组进行排序),但我无法让它发挥作用。

这是我尝试对哈希执行的子例程:

sub gpa_hash{

    my @gpavalues = sort { $stud_gpa{$a} <=> $stud_gpa{$b} } keys %stud_gpa;
    my $highest = $gpavalues[-1];
    my $smallest = $gpavalues[0];
    print "the max GPA is $highest of the student $stud_gpa{$gpavalues[-1]}<br>";
    print "the min GPA is $smallest of the student $stud_gpa{$gpavalues[0]}<br>";

}

但我的输出有些问题,因为这是我得到的:

the max GPA is of the student 
the min GPA is of the student 

然后我尝试了一个数组,看看它是否更容易理解:

my @tot_gpa = (
           \$gpa_one,
           \$gpa_two,
           \$gpa_three,
           \$gpa_four,
           \$gpa_five,
           \$gpa_six,
           \$gpa_seven,
           \$gpa_eight,
           \$gpa_nine,
           \$gpa_ten
);

sub gpa{
    my $max = (sort { $a <=> $b } @tot_gpa)[-1];
    my $min = (sort { $a <=> $b } @tot_gpa)[0];
    print "this is the smallest GPA: $min<br>";
    print "this is the highest GPA: $max<br>";
}

但这就是我得到的:

this is the smallest GPA: SCALAR(0x8bcab0)
this is the highest GPA: SCALAR(0x8bcbd0)

我确定我首先在将变量分配给数组时做错了,因为如果我只是打印数组本身,它会给我这个输出:

SCALAR(0x8bcab0)
SCALAR(0x8bcad0)
SCALAR(0x8bcaf0)
SCALAR(0x8bcb10)
SCALAR(0x8bcb30)
SCALAR(0x8bcb50)
SCALAR(0x8bcb70)
SCALAR(0x8bcb90)
SCALAR(0x8bcbb0)
SCALAR(0x8bcbd0)

如果我只打印 GPA 变量,我会得到正确的对应数字,就像 print "$gpa_one&lt;br&gt;"; 给了我(例如)2.1。有人可以帮助我了解如何解决它吗?我要疯了……

谢谢!

【问题讨论】:

  • 是的,我也在使用use warnings;use strict;,但它并没有给我任何错误,可能是因为语法似乎正确.. 我只是使用了$gpa_one 和所有其他的值在他们自己的子程序中给他们结果,就像这样$gpa_one = $sum/$average所以如果我只打印$gpa_one它可以工作,它给了我输入表格的正确gpa,但问题是当我通过它时在数组或哈希内
  • 您的声明my @name = $cgi-&gt;param('name')name 字符串放入$name[0]。其余的元素,$name[1] 之后,仍然未定义,您可能会收到关于 Use of uninitialized value 的警告。

标签: arrays perl sorting hash


【解决方案1】:

sort 返回其 输入列表 排序,所以在你的子

sub gpa_hash {

    my @gpavalues = sort { $stud_gpa{$a} <=> $stud_gpa{$b} } keys %stud_gpa;
    my $highest = $gpavalues[-1];
    my $smallest = $gpavalues[0];
    ...
}

@gpavalues 不是值,而是键,按块中的条件排序。

所以你可以通过

来检索值
my $largest  = $stud_gpa{$gpavalues[-1]};
my $smallest = $stud_gpa{$gpavalues[0]};

my ($largest, $smallest) = @stud_gpa{ @gpavalues[-1,0] };

通过使用数组和哈希slices

一些通用的cmets。

您似乎将变量设置为全局变量,以便子例程可以看到它们。这似乎可行,但随着程序变得更加复杂,它肯定会导致麻烦。您应该始终编写您的潜艇以通过参数从调用代码中获取他们需要的数据。

我不知道手动列出所有$gpa_N 的目的,但它们显然应该是(未命名的)多值数据类型或变量的元素,例如数组。鉴于您随后将它们分配给哈希值,您可能会在获得这些值时正确执行此操作。

【讨论】:

    【解决方案2】:
    SCALAR(0x8bcbd0)
    

    表示您正在标量上打印引用

    您必须取消引用才能打印标量而不是其地址

    这将通过替换来完成

    my $max = (sort { $a <=> $b } @tot_gpa)[-1];
    

    通过

    my $max = ${(sort { int($$a) <=> int($$b) } @tot_gpa)[-1]};
    

    $ 开头和之前的 $a$b 取消引用您的标量。 只有$a$b 你会排序地址,而不是值

    int 强制 int 上下文比较数字而不是字符串

    你也可以用变量而不是引用来填充你的数组,比如

    my ($gpa_one, $gpa_two, $gpa_three, $gpa_four) = (12.5,15.8,1,2.5);
    
    my @tot_gpa = (
              $gpa_one, 
              $gpa_two, 
              $gpa_three, 
              $gpa_four
    );
    
    my $max = (sort { $a <=> $b } @tot_gpa)[-1];
    print $max;
    

    打印15.8

    现在我尝试了你的哈希:

    use strict;
    use warnings;
    
    my ($gpa_one, $gpa_two, $gpa_three, $gpa_four) = (12.5,15.8,1,2.5);
    
    my %stud_gpa = (
    'a' => $gpa_one,
    'b' => $gpa_two,
    'c' => $gpa_three,
    'd' => $gpa_four,
    
    );
    
    sub gpa_hash{
    
        my @gpavalues = sort { $stud_gpa{$a} <=> $stud_gpa{$b} } keys %stud_gpa;
        my $highest = $gpavalues[-1];
        my $smallest = $gpavalues[0];
        print "the max GPA is $highest of the student $stud_gpa{$gpavalues[-1]}<br>";
        print "the min GPA is $smallest of the student $stud_gpa{$gpavalues[0]}<br>";
    
    }
    
    gpa_hash();
    

    它打印the max GPA is b of the student 15.8&lt;br&gt;the min GPA is c of the student 1

    所以 name 和 gpa 被切换了,这是因为 $highest$smallest 包含您在 keys %stud_gpa 上进行排序时的学生姓名

    我无法重现您的问题

    它可以产生您所描述的方式是您的$gpa 是引用。 像你已经做的那样声明你的哈希并修改你的gpa_hash如下,这应该可以工作

    sub gpa_hash{
    
        my @gpavalues = sort { ${$stud_gpa{$a}} <=> ${$stud_gpa{$b}} } keys %stud_gpa;
        my $highest = $gpavalues[-1];
        my $smallest = $gpavalues[0];
        print "the max GPA is ${$stud_gpa{$highest}} of the student $highest<br>";
        print "the min GPA is ${$stud_gpa{$smallest}} of the student $smallest <br>";
    
    }
    

    【讨论】:

    • 谢谢,我现在就这样试试,其他部分的代码呢?以我对哈希和数组的方式分配标量是否正确?因为它打印引用而不是相应的值,即使我只打印数组的每个元素,如我所示
    • 是的,因为你用引用填充了你的数组(变量之前的\ )。另一种解决方案是用变量本身填充你的数组(通过删除 \ ),这样你就必须让你的代码保持现在的状态,比如 my $max = (sort { $a &lt;=&gt; $b } @tot_gpa)[-1];
    • 我尝试了两种方法,你告诉的第一个方法现在与数组完美配合,而如果我尝试从变量中删除 \ 并使用 my $max = (sort { $a &lt;=&gt; $b } @tot_gpa)[-1]; 它又给了我参考SCALAR(0x8eefd0)... 但至少第一个效果很好! :) 有没有办法取消引用散列中的标量?
    • @Mattia:你为什么首先使用引用。您在第一个示例中没有这样做,但在第二个示例中,您将 \$gpa_one 等引用分配给 @tot_gpa
    猜你喜欢
    • 2011-12-31
    • 2018-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-01
    • 2019-05-26
    • 2017-09-30
    • 2021-07-09
    相关资源
    最近更新 更多