操纵和访问哈希散列的内容

时间:2016-12-31 10:30:12

标签: perl

我在编写Perl脚本时遇到了麻烦。

这是任务:

question for perl script

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

  1. 我想在哈希%grocery中添加一个元素,其中包含类别,品牌和价格。添加项目时,首先系统会询问类别。

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

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

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

    我做错了什么?

  3. 这是我的完整代码:

    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 );
    

3 个答案:

答案 0 :(得分: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;

我已通过评论标记了上述相关部分。您可以在以下文档中阅读这些内容:perlreftutperllolperldscperlref

  

此问题与最大值有关。查找给定哈希值的最大值。我正在为此获得垃圾价值。

这个问题也是基于你还没有理解参考文献的事实。

 $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

答案 1 :(得分:2)

对于类别已存在且何时不存在,您具有完全相同的代码。这条线

August 28, 2016 at 09:20AM = 2
August 28, 2016 at 09:26AM = 3

替换类别$grocery{$c} = { $b, $p }; 的整个哈希值。这对于新类别来说很好,但是如果该类别已经存在,那么它将丢弃任何现有信息

你需要写

$c

请在运算符周围添加更多空格,分隔列表元素,并描述相关的语句序列


关于找到最高价格,您的行

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

正在尝试计算与类别

对应的哈希引用的最大值

由于此处有两个哈希级别,您需要

$highest = max values %grocery;

但这可能不是您期望的方式。如果有疑问,那么你应该使用两个嵌套的$highest = max map { values %$_ } values %grocery; 循环

答案 2 :(得分:-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 );
}