2011-02-03 67 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! 
} 

这可能是很好的 - 它可以让你修改传递给子程序的数据,或不好 - 它允许你无意中将修改数据传递给原来的子程序。

相关问题