我希望通过多次应用函数来连续填充哈希表。该函数在参数中使用哈希引用,填充它并返回它。该函数在参数中再次获取哈希值。 似乎哈希根本没有填充。
这是我的代码:
有人能告诉我哪里可能有错误吗?
sub extractMLResult {
my (%h1, %h2, %h3, %h4, $param) = @_;
my $h1= shift;
my $h2= shift;
my $h3= shift;
my $h4=shift;
$params= shift;
# read csv file, split it, fill hashes with values
$h1->{$key1}{$key2}{'p'}=$val1;
# ... do the same for the other hashes ...
return (%$h1, %$h2, %$h3, %$h4);
}
my %myhash = ();
my %h1= ();
my %h2= ();
my %h3= ();
my %h4= ();
$myhash{'a'}{'x'}=1;
$myhash{'b'}{'y'}=1;
if (exists $myhash{'a'}){
(%h1, %h2, %h3, %h4) = extractMLResult(\%h1, \%h2, \%h3, \%h4, 'a');
}
if (exists $myhash{'b'}){
(%h1, %h2, %h3, %h4) = extractMLResult(\%h1, \%h2, \%h3, \%h4, 'b');
}
答案 0 :(得分:2)
my
在词法范围内声明变量。因此,当您退出“if”子句时,%$h1
等会再次消失。
另外,你在做分配方面做了一些奇怪的事情,我认为这不会像你想象的那样工作 - 你正在引用你的哈希引用,并因此返回一个值列表。
由于列表分配的工作方式,所有将进入%$h1
。
但另一方面 - 当你在myfunction
中阅读时,你的作业可能没有按照你的想法行事。
因为您正在调用myfunction
并传递值列表,但您正在为%h1
执行列表分配。这意味着你所有的论据都被“消耗”了:
#!/usr/bin/env perl
use strict;
use warnings;
use Data::Dumper;
sub myfunction {
my (%h1, %h2, %h3, %h4, $param) = @_;
print Dumper \%h1;
print Dumper \%h2;
}
# launch function :
my %h1 = ( a => "test" );
my %h2 = ( b => "wibble" );
myfunction ( \%h1, \%h2 );
正如您将看到的那样 - 您的参数全部由%h1
的作业消耗,其余任务都没有。
更重要的是 - 您的代码甚至无法编译,因为如果您这样做:
my (%$h1, %$h2, %$h3, %$h4) = myfunction (\%h1, \%h2, \%h3, \%h4, "a");
你得到:
Can't declare hash dereference in "my"
所以也许给我们一些实际说明问题的示例代码 - 并运行一些示例数据?
编辑:使用更多代码 - 问题就在这里:
sub extractMLResult {
my (%h1, %h2, %h3, %h4, $param) = @_;
因为那不符合你的想法。因为%h1
是一个哈希值,并且它是在列表上下文中分配的 - 所有@_
的参数都插入其中。因此%h2, %h3, %h4, $param
将始终为空/未定义。
你并没有表明你是否实际使用%h1
,这只是意味着它是混乱的废话 - 可能。
但是这一点:
my $h1= shift;
my $h2= shift;
my $h3= shift;
my $h4_parents = shift;
好的,所以你在这里提取一些哈希引用,这可能更加理智。但是命名与哈希相同是令人困惑的 - $h1
和%h1
之间存在 NO 关系,如果你这样做,你会在代码中混淆。 (因为$h1{key}
来自%h1
而与$h1
无关。)
但回归中存在同样的问题:
(%h1, %h2, %h3, %h4) = extractMLResult(\%h1, \%h2, \%h3, \%h4, 'a');
因为您的return
:
return (%$h1, %$h2, %$h3, %$h4);
此返回将返回包含散列中所有元素的展开列表。但考虑到你打包哈希的方式,它们可能是部分展开的列表,包含哈希引用。
但是,在作业中,他们将所有再次由%h1
消费。
你需要:
返回($ h1,$ h2,$ h3,$ h4);
然后在你的函数中:
($ h1_ret,$ h2_ret,$ h3_ret,$ h4_ret)= extractMLResult(\%h1,\%h2,\%h3,\%h4,'a');
然后解压缩:
%h1 = %$h1_ret;
或者只是坚持使用参考文献,这对所有相关人员来说可能更清楚。
答案 1 :(得分:1)
You are passing hash references into your subroutine. This is a good idea. But inside your subroutine, you are treating your parameters as hashes (not hash references). This is a bad idea.
A hash is initialised from a list. It should be a list with an even number of elements. Each pair of elements in the list will become a key/value pair in the hash.
my %french => ('one', 'un', 'two', 'deux', 'three', 'trois');
We often use the "fat comma" to emphasise the link between keys and values.
my %french => (one => 'un', two => 'deux', three => 'trois');
This means that hash initialisation is a greedy operation. It will use up all of any list that it is given. You cannot initialise two hashes in the same statement:
my (%french, %german) = (one => 'un', two => 'deux',
three => 'drei', four => 'vier');
This doesn't work, as all of the pairs will end up in %french
, leaving nothing to populate %german
.
This is the same mistake that you are making when extracting the parameters within your subroutine. You have this:
my (%h1, %h2, %h3, %h4, $param) = @_;
Nothing will end up in %h2,
%h3,
%h4or
$paramas the assignment to
%his greedy and will take all of the data values from
@_` - leaving nothing for the other variables.
But, as you are passing hash references, your code shouldn't look like that. A hash reference is a scalar value (that's pretty much the point of them) so it is stored in a scalar variable.
What you want is this:
# Note, scalars ($), not hashes (%)
my ($h1, $h2, $h3, $h4, $param) = @_;
This should get you started. Note also, that you'll now need to deal with hash references ($h1->{key}
) rather than hashes ($h1{key}
).
And, please, always include both use strict
and use warnings
.