2016-12-31 68 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