25

需要帮助弄清楚如何做到这一点。我的代码:

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";
    }
}
4

5 回答 5

40

当代码演变时可能会导致问题的简单方法是将默认数组@_(包含所有键值对作为偶数列表)分配给 %hash,然后相应地重新构建。所以你的代码看起来像这样:

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

更好的方法是将散列作为对子例程的引用。这样您仍然可以将更多参数传递给您的子例程。

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

可以在perlreftut中找到在 Perl 中使用引用的介绍

于 2011-02-04T00:00:10.940 回答
8

你是如此非常非常接近。没有%_用于传递哈希,它必须传入@_。幸运的是,哈希是使用列表上下文分配的,所以

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

会成功的!

另请注意,&在大多数情况下,至少从 Perl 5.000 开始,在子例程调用前面使用 是不必要的。您可以像现在在其他语言中一样调用 Perl 子例程,只需使用名称和参数。(正如@mob 在评论中指出的那样,在某些情况下这仍然是必要的;如果有兴趣,请参阅perlsub以进一步了解这一点。)

于 2011-02-03T23:54:38.823 回答
7

传递哈希和数组的最佳方式是通过引用。引用只是将复杂数据结构作为单个数据点讨论的一种方式——可以存储在标量变量(如$foo)中的东西。

阅读参考资料,以便您了解如何创建参考资料和取消参考资料以获取原始数据。

最基本的:你在你的数据结构前面加上一个反斜杠来获取对该结构的引用

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)

要将引用恢复为可用格式,您只需将引用放入正确的 符号前面:

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!
}

这可能很好——它允许您修改传递给子例程的数据,或者不好——它允许您无意中修改传递给原始子例程的数据。

于 2013-08-20T17:11:46.103 回答
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它从列表中的交替元素中再次创建具有相应值的键。

于 2011-02-03T23:54:39.550 回答
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);

警告:原型不适用于方法。

于 2011-02-04T00:36:33.213 回答