更新时间:2022-10-26 23:38:09
简单的哈希函数接近数组。他们的初始化甚至看起来相似。首先是数组:
@last_name =(
Ward,Cleaver,
Fred ,Flintstone,
Archie,Bunker
);
现在让我们使用散列表示相同的信息(又名关联数组):
%last_name =(
Ward,Cleaver,
Fred,Flintstone,
Archie,Bunker
);
尽管它们具有相同的名称,但数组 @last_name
和散列%last_name
是完全独立的。
有了数组,如果我们想知道Archie的姓氏,我们必须执行线性搜索:
my $ lname; ($ my $ i = 0; $ i $ lname = $ last_name [$ i + 1]
if $ last_name [$ i] eq阿尔奇;
}
打印Archie $ lname\\\
;
使用散列,它在语法上更直接:
打印Archie $ last_name {Archie} \\\
;
假设我们只想用稍微丰富的结构表示信息:
在引用出现之前,平键值散列是我们可以做的***的,但引用允许
my% personal_info =(
Cleaver,{
FIRST,Ward,
SPOUSE,June,
},
Flintstone, {
FIRST,Fred,
SPOUSE,Wilma,
},
Bunker,{
FIRST,Archie ,
SPOUSE,Edith,
},
);
在内部,%personal_info
都是标量,但这些值是一种特殊的标量:使用 {}
创建的哈希引用。这些参考使我们能够模拟多维哈希。例如,我们可以通过
$ personal_info {Flintstone} - > {SPOUSE}
请注意,Perl允许我们在下标之间省略箭头,所以上面的内容相当于
$ personal_info {Flintstone} {SPOUSE}
如果您想了解有关Fred的更多信息,那么您可以输入很多内容,因此您可以使用某种游标获取引用:
$ fred = $ personal_info {Flintstone};
printFred的妻子是$ fred-> {SPOUSE} \\\
;
因为上面代码片段中的 $ fred
是一个hashref,箭头是必要的。如果你放弃它,但明智地启用使用strict
来帮助你捕捉这些类型的错误,编译器会抱怨:
全局符号%fred需要显式包名称...
Perl引用与C和C ++中的指针类似,但它们不能为空。 C和C ++中的指针需要解引用,因此需要在Perl中引用。
C和C ++函数参数具有按值传递的语义:它们只是副本,不要回到调用者。如果你想看到更改,你必须传递一个指针。您可以在Perl中使用引用来获得这种效果:
sub add_barney {
my($ personal_info)= @_;
$ personal_info-> {Rubble} = {
FIRST => Barney,
SPOUSE => 贝蒂,
};
}
add_barney \%personal_info;
没有反斜线, add_barney
一个副本在子回来后立即抛出。
还要注意使用胖逗号( =>
)以上。它会自动引用左侧的字符串,并使得哈希初始化的语法更少。
I would like to properly understand hashes in Perl. I've had to use Perl intermittently for quite some time and mostly whenever I need to do it, it's mostly related to text processing.
And everytime, I have to deal with hashes, it gets messed up. I find the syntax very cryptic for hashes
A good explanation of hashes and hash references, their differences, when they are required etc. would be much appreciated.
A simple hash is close to an array. Their initializations even look similar. First the array:
@last_name = (
"Ward", "Cleaver",
"Fred", "Flintstone",
"Archie", "Bunker"
);
Now let's represent the same information with a hash (aka associative array):
%last_name = (
"Ward", "Cleaver",
"Fred", "Flintstone",
"Archie", "Bunker"
);
Although they have the same name, the array @last_name
and the hash %last_name
are completely independent.
With the array, if we want to know Archie's last name, we have to perform a linear search:
my $lname;
for (my $i = 0; $i < @last_name; $i += 2) {
$lname = $last_name[$i+1] if $last_name[$i] eq "Archie";
}
print "Archie $lname\n";
With the hash, it's much more direct syntactically:
print "Archie $last_name{Archie}\n";
Say we want to represent information with only slightly richer structure:
Before references came along, flat key-value hashes were about the best we could do, but references allow
my %personal_info = (
"Cleaver", {
"FIRST", "Ward",
"SPOUSE", "June",
},
"Flintstone", {
"FIRST", "Fred",
"SPOUSE", "Wilma",
},
"Bunker", {
"FIRST", "Archie",
"SPOUSE", "Edith",
},
);
Internally, the keys and values of %personal_info
are all scalars, but the values are a special kind of scalar: hash references, created with {}
. The references allow us to simulate "multi-dimensional" hashes. For example, we can get to Wilma via
$personal_info{Flintstone}->{SPOUSE}
Note that Perl allows us to omit arrows between subscripts, so the above is equivalent to
$personal_info{Flintstone}{SPOUSE}
That's a lot of typing if you want to know more about Fred, so you might grab a reference as sort of a cursor:
$fred = $personal_info{Flintstone};
print "Fred's wife is $fred->{SPOUSE}\n";
Because $fred
in the snippet above is a hashref, the arrow is necessary. If you leave it out but wisely enabled use strict
to help you catch these sorts of errors, the compiler will complain:
Global symbol "%fred" requires explicit package name at ...
Perl references are similar to pointers in C and C++, but they can never be null. Pointers in C and C++ require dereferencing and so do references in Perl.
C and C++ function parameters have pass-by-value semantics: they're just copies, so modifications don't get back to the caller. If you want to see the changes, you have to pass a pointer. You can get this effect with references in Perl:
sub add_barney {
my($personal_info) = @_;
$personal_info->{Rubble} = {
FIRST => "Barney",
SPOUSE => "Betty",
};
}
add_barney \%personal_info;
Without the backslash, add_barney
would have gotten a copy that's thrown away as soon as the sub returns.
Note also the use of the "fat comma" (=>
) above. It autoquotes the string on its left and makes hash initializations less syntactically noisy.