2016-12-31 36 views
-1

我在编写Perl脚本时遇到了问题。操作和访问哈希散列的内容

这是任务:

question for perl script

我的代码工作正常,但有两个问题。

  1. 我想添加一个元素到散列%grocery,其中包含类别,品牌和价格。添加项目时,首先系统会要求提供该类别。

    如果该类别不存在,则会从用户添加新的类别,品牌和价格,但是如果该类别已经存在,那么它将采用用户的品牌名称和价格,并将其附加到现有类别。

    当我尝试这样做时,它会清除先前存在的项目。我希望以前的项目添加新添加的项目。

  2. 此问题与最大值有关。查找给定哈希中的最大价格。我为此获得了垃圾价值。

    我在做什么错?

这里是我的全码:

use strict; 
use warnings; 

use List::Util qw(max); 
use feature "switch"; 

my $b; 
my $c; 
my $p; 
my $highest; 

print "____________________________STORE THE ITEM_____________________\n"; 

my %grocery = (
    "soap"  => { "lux" => 13.00, "enriche" => 11.00 }, 
    "detergent" => { "surf" => 18.00 }, 
    "cleaner" => { "domex" => 75.00 } 
); 

foreach my $c (keys %grocery) { 
    print "\n"; 
    print "$c\n"; 
    foreach my $b (keys %{ $grocery{$c} }) { 
     print "$b:$grocery{$c}{$b}\n"; 
    } 
} 

my $ch; 

do { 
    print "________________MENU_________________\n"; 
    print "1.ADD ITEM\n"; 
    print "2.SEARCH\n"; 
    print "3.DISPLAY\n"; 
    print "4.FIND THE MAX PRICE\n"; 
    print "5.EXIT\n"; 
    print "enter your choice \n"; 
    $ch = <STDIN>; 
    chomp($ch); 

    given ($ch) { 

     when (1) { 
      print "Enter the category you want to add"; 
      $c = <STDIN>; 
      chomp($c); 

      if (exists($grocery{$c})) { 

       print "Enter brand\n"; 
       $b = <STDIN>; 
       chomp($b); 

       print "Enter price\n"; 
       $p = <STDIN>; 
       chomp($p); 

       $grocery{$c} = { $b, $p }; 

       print "\n"; 
      } 
      else { 

       print "Enter brand\n"; 
       $b = <STDIN>; 
       chomp($b); 

       print "Enter price\n"; 
       $p = <STDIN>; 
       chomp($p); 

       $grocery{$c} = { $b, $p }; 

       print "\n"; 
      } 
     } 

     when (2) { 

      print "Enter the item that you want to search\n"; 
      $c = <STDIN>; 
      chomp($c); 

      if (exists($grocery{$c})) { 

       print "category $c exists\n\n"; 
       print "Enter brand\n"; 
       $b = <STDIN>; 
       chomp($b); 

       if (exists($grocery{$c}{$b})) { 
        print "brand $b of category $c exists\n\n"; 
        print "-----$c-----\n"; 
        print "$b: $grocery{$c}{$b}\n"; 
       } 
       else { 
        print "brand $b does not exists\n"; 
       } 
      } 
      else { 
       print "category $c does not exists\n"; 
      } 
     } 

     when (3) { 

      foreach $c (keys %grocery) { 

       print "$c:\n"; 

       foreach $b (keys %{ $grocery{$c} }) { 
        print "$b:$grocery{$c}{$b}\n"; 
       } 
      } 
     } 

     when (4) { 

      print "\n________________PRINT HIGHEST PRICED PRODUCT____________________\n"; 
      $highest = max values %grocery; 
      print "$highest\n"; 
     } 
    } 

} while ($ch != 5); 
+0

你有没有被教过使用'given' /'when'?这是一个*实验*功能,所以它的功能可能会改变,或者在将来的Perl版本中可能会完全消失。最好避免它。 – Borodin

+0

不要使用单字符变量名称,除非它们是像索引'$ i'或通用字符串'$ s'一样建立的。 '$ a'和'$ b'是保留的标识符,应该完全避免。 – Borodin

+1

完成任务后,我建议您在[codereview.se]上发布它,然后我们会告诉您如何改进它。 – simbabque

回答

4

当我尝试这样做,它会清除预先存在的项目。我希望以前的项目添加新添加的项目。

在这一行中,您将用新的散列引用覆盖$grocery{$c}的值。

$grocery{$c}={$b,$p}; 

相反,你需要编辑现有的散列引用。

$grocery{$c}->{$b} = $p; 

这将增加一个新的关键$b到现有的数据结构的$grocery{$b}内,分配给它的$p值。

让我们来看看这意味着什么。在%grocery被初始化后,我已将此代码添加到代码中。

use Data::Dumper; 
print Dumper \%grocery; 

我们将得到以下输出。哈希没有排序,所以顺序可能会有所不同。

$VAR1 = { 
     'cleaner' => { 
        'domex' => '75' 
        }, 
     'detergent' => { 
         'surf' => '18' 
        }, 
     'soap' => { 
        'enriche' => '11', 
        'lux' => '13' 
       } 
    }; 

正如你所看到的,我们在哈希里面有哈希。在Perl中,引用用于构造多级数据结构。你可以在输出中看到花括号{}$VAR1之后的第一个是因为我在前面添加了反斜杠\,我通过参考$groceryDumper

因此,$grocery{"cleaner"}的值的后面是散列参考{ "domex" => 75 }。要涉及该散列引用,您需要使用引用运算符->。然后你可以把一个新的密钥放入这个哈希引用中,就像我上面展示的那样

#     ##!!!!!!!!!! 
$grocery{"cleaner"}->{"foobar"} = 30; 

我已在上述相关部分标注了评论。您可以在这些文档中阅读这些内容:perlreftut,perllolperldscperlref


这个问题是与最大值。查找给定散列值的最大值。我为此获得了垃圾价值。

此问题也是基于您尚未理解引用的事实。

$highest = max values %grocery; 

您的代码将只需要直接在%grocery值。如果向上滚动并再次查看Dumper输出,则会看到%grocery中有三个哈希引用。现在,如果您不取消引用他们,您只需获得他们的标量表示法。 Perl中的标量是单个值,如数字或字符串。但对于参考文献而言,这是他们的类型和地址看起来像垃圾的实际上是%grocery中具有最高数字的三个散列引用的内存地址。

当然,这不是你想要的。您需要迭代您的数据结构的两个级别,收集所有值,然后找到最高的值。

my @all_prices; 
foreach my $category (keys %grocery) { 
    push @all_prices, values %{ $grocery{$category} }; 
} 
$highest = max @all_prices; 
print "$highest\n"; 

我选择了一个非常详细的方法来做到这一点。它遍历%grocery中的所有类别,然后获取存储在它们后面的散列引用的所有values。那些被添加到数组中,最后我们可以从数组中取出所有这些数组中的max

+0

以及如何显示具有最高价格的类别和品牌详情 – ayav

+0

以及如何显示价格最高的类别和品牌细节@simbabque – ayav

+0

@ayav这更加棘手。您需要自己找到最大值,并记住其余的数据。告诉你如何做到这一点并不会帮助你学习。 – simbabque

2

对于类别已存在和不存在时,您具有完全相同的代码。该生产线

$grocery{$c} = { $b, $p }; 

取代$c产品的整体哈希值。这很好的新的类别,但如果类是已经存在那么它将扔掉任何现有信息

你需要写

$grocery{$c}{$b} = $p; 

并请加很多空白的运营商,分离列表的元素,和语句划分中相关序列



对于找到的最高价格,你行

$highest = max values %grocery; 

试图计算最大的哈希引用对应

由于有散列的两个级别在这里,你需要的类别

$highest = max map { values %$_ } values %grocery; 

但这可能不是您期望的方式。如果有疑问,那么你应该使用两个嵌套for回路

-3
use List::Util qw(max); 
use Data::Dumper; 

my $grocery = 
{ 
    "soap"  => { "lux" => 13.00, "enriche" => 11.00 }, 
    "detergent" => { "surf" => 18.00 }, 
    "cleaner" => { "domex"=> 75.00 } 
}; 

display("unadulterated list"); 
print Dumper $grocery; 

display("new silky soap"); 
$grocery->{"soap"}->{"silky"} = 12.50; 
print Dumper $grocery; 

display("new mega cleaner"); 
$grocery->{"cleaner"}->{"megaclean"} = 99.99; 
print Dumper $grocery; 

display("new exfoliant soap"); 
$grocery->{"soap"}->{"exfoliant"} = 23.75; 
print Dumper $grocery; 

display("lux soap gets discounted"); 
$grocery->{"soap"}->{"lux"} = 9.00; 
print Dumper $grocery; 

display("domex cleaner is discontinued"); 
delete $grocery->{"cleaner"}->{"domex"}; 
print Dumper $grocery; 

display("most costly soap product"); 
my $max = max values $grocery->{soap}; 
print $max, "\n\n"; 

sub display 
{ 
    printf("\n%s\n%s\n%s\n\n", '-' x 45, shift, '-' x 45); 
} 
+3

这有什么用?请解释你的代码,以及为什么你认为它回答了这个问题。 – simbabque