2011-02-03 16 views
16

需要幫助搞清楚如何做到這一點。我的代碼:如何將散列傳遞給子例程?

my %hash; 
$hash{'1'}= {'Make' => 'Toyota','Color' => 'Red',}; 
$hash{'2'}= {'Make' => 'Ford','Color' => 'Blue',}; 
$hash{'3'}= {'Make' => 'Honda','Color' => 'Yellow',}; 


&printInfo(%hash); 

sub printInfo{ 
    my (%hash) = %_; 
    foreach my $key (keys %_{  
    my $a = $_{$key}{'Make'}; 
    my $b = $_{$key}{'Color'}; 
    print "$a $b\n"; 
    } 
} 

回答

27

當代碼發展時,可能會導致問題的簡單方法就是簡單地將默認數組@_(其中包含所有鍵值對作爲偶數列表)分配給%散列,然後重新編譯。因此,您的代碼如下所示:

sub printInfo { 
    my %hash = @_; 
    ... 
} 

更好的方法是將散列作爲參考傳遞給子例程。這樣你仍然可以將更多的參數傳遞給你的子程序。

printInfo(\%hash); 
sub PrintInfo { 
    my %hash = %{$_[0]}; 
    ... 
} 

使用在Perl引用的介紹可以在perlreftut

8

你是如此非常非常接近。沒有%_用於傳遞哈希,它必須通過@_。幸運的是,哈希使用列表上下文進行分配,因此

sub printInfo { 
    my %hash = @_; 
    ... 
} 

將使其工作!

另請注意,在子程序調用前使用&在大多數情況下是不必要的,因爲至少是Perl 5.000。您可以像現在其他語言一樣調用Perl子例程,僅使用名稱和參數。 (由於@mob在評論中指出,有一些情況下這哪裏還是有必要的;見perlsub明白這更,如果有興趣。)

+0

`&`通常是可選的,並且由於Perl生成默認參數的方式(通常)不是最佳實踐,因此它不被棄用。有時它是必需的,有時它不是必需的,但它仍然可以使代碼更具可讀性。 – mob 2011-02-04 00:03:13

+0

您,先生,技術上是正確的:最好的一種正確的。我已經澄清了我對此的評論。 – 2011-02-04 00:52:17

+1

不*「也許更老」*。在1993年2月05日的最後一個perl4版本4.036中,函數調用中通常需要**。相信我,我在那裏。 ☺避免這種情況的唯一方法是使用`do mysubname()`語法 - 順便說一下,它仍然可以正常工作,這對於那些偶然發現的少數人來說是驚喜。或者在它之上。 – tchrist 2011-02-04 01:07:57

6

我相信你想

my %hash; 
$hash{'1'}= {'Make' => 'Toyota','Color' => 'Red',}; 
$hash{'2'}= {'Make' => 'Ford','Color' => 'Blue',}; 
$hash{'3'}= {'Make' => 'Honda','Color' => 'Yellow',}; 

printInfo(%hash); 

sub printInfo{ 
    my %hash = @_; 
    foreach my $key (keys %hash){  
    my $a = $hash{$key}{'Make'}; 
    my $b = $hash{$key}{'Color'}; 
    print "$a $b\n"; 
    } 
} 

在行printInfo(%hash)%hash擴展爲具有交替鍵值對的列表。

printInfo中,@_是該列表,並且被分配到%hash,它再次創建具有來自列表中交替元素的對應值的鍵。

3

找到您可以將它們作爲

  1. 參數列表do_hash_thing(%hash)
  2. 在參數的引用到哈希列表 `do_hash_thing(@args_before,\%hash,@args_after)
  3. 作爲原型,像keys和其他哈希運算符一樣工作。

名單的工作原理是這樣:

sub do_hash_thing { 
    my %hash = @_; 
    ... 
} 

do_hash_thing(%hash); 

這也讓你 「流」 的哈希參數,以及:

do_hash_thing(%hash_1, %hash_2, parameter => 'green', other => 'pair'); 

通過引用是這樣的:

sub do_hash_thing { 
    my $hash_ref = shift; 
    ... 
} 

do_hash_thing(\%hash, @other_args); 

這裏通過原型(\%@)。原型使perl在第一個參數中查找一個散列並通過引用傳遞它。

sub do_hash_thing (\%@) { 
    my $hash_ref = shift; 
    ... 
} 

do_hash_thing(%hash => qw(other args)); 
# OR 
do_hash_thing %hash => qw(other args); 

警告:原型不適用於方法。

4

傳遞哈希和數組的最好方法是reference。參考僅僅是一種將複雜數據結構作爲單個數據點來討論的方式 - 可以存儲在標量變量(如$foo)中的東西。

請閱讀references,以便您瞭解如何創建參考文件並取消參考以獲取原始數據。

非常基礎:您在數據結構之前加上一個反斜槓,以便將引用引用到該結構中。

my $hash_ref = \%hash; 
my $array_ref = \@array; 
my $scalar_ref = \$scalar; #Legal, but doesn't do much for you... 

的引用是原始結構的存儲位置(加上一個關於結構線索):

print "$hash_ref\n"; 

將打印類似:

HASH(0x7f9b0a843708) 

要獲得基準迴轉換爲可用格式,您只需將參考文件放在前面的正確sigil即可:

my %new_hash = %{ $hash_ref }; 

您應該瞭解如何使用引用,因爲這是您可以在Perl中創建極其複雜的數據結構以及面向對象的Perl如何工作的方式。


假設您想要將三個哈希值傳遞給您的子程序。這裏有三個散列:

my %hash1 = (this => 1, that => 2, the => 3, other => 4); 
my %hash2 = (tom => 10, dick => 20, harry => 30); 
my %hash3 = (no => 100, man => 200, is => 300, an => 400, island => 500); 

,我會爲他們創造

my $hash_ref1 = \%hash1; 
my $hash_ref2 = \%hash2; 
my $hash_ref3 = \%hash3; 

而且現在引用剛剛通過引用:

mysub ($hash_ref1, $hash_ref2, $hash_ref3); 

的參考文獻數據,所以將它們傳遞給我的子程序沒有任何問題:

sub mysub { 
    my $sub_hash_ref1 = shift; 
    my $sub_hash_ref2 = shift; 
    my $sub_hash_ref3 = shift; 

現在,我只是提領他們,我的子程序可以使用它們。

my %sub_hash1 = %{ $sub_hash_ref1 }; 
    my %sub_hash2 = %{ $sub_hash_ref2 }; 
    my %sub_hash3 = %{ $sub_hash_ref3 }; 

你可以看到一個參考是什麼參考使用ref命令:

my $ref_type = ref $sub_hash_ref; # $ref_type is now equal to "HASH" 

如果你想確保你傳遞的正確類型的數據結構,這是有用。

sub mysub { 
    my $hash_ref = shift; 

    if (ref $hash_ref ne "HASH") { 
     croak qq(You need to pass in a hash reference); 
    } 

另外請注意,這些內存引用,因此修改引用將修改原來的哈希:

my %hash = (this => 1, is => 2, a => 3 test => 4); 
print "$hash{test}\n"; # Printing "4" as expected 
sub mysub (\%hash); # Passing the reference 
print "$hash{test}\n"; # This is printing "foo". See subroutine: 


sub mysub { 
    my $hash_ref = shift; 

    $hash_ref->{test} = "foo"; This is modifying the original hash! 
} 

這可能是很好的 - 它可以讓你修改傳遞給子程序的數據,或不好 - 它允許你無意中將修改數據傳遞給原來的子程序。

相關問題