Perl 中的散列和散列引用有什么区别? [英] What's the difference between a hash and hash reference in Perl?

查看:32
本文介绍了Perl 中的散列和散列引用有什么区别?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想正确理解 Perl 中的哈希值.我不得不断断续续地使用 Perl 很长一段时间,而且主要是每当我需要使用它时,它主要与文本处理有关.

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"
);

虽然名称相同,但数组@last_name和散列%last_name是完全独立的.

Although they have the same name, the array @last_name and the hash %last_name are completely independent.

有了数组,如果我们想知道 Archie 的姓氏,就必须进行线性搜索:

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

使用哈希,它在语法上更直接:

With the hash, it's much more direct syntactically:

print "Archie $last_name{Archie}
";

假设我们只想用稍微丰富的结构来表示信息:

Say we want to represent information with only slightly richer structure:

  • Cleaver(姓氏)
    • 病房(名字)
    • 六月(配偶的名字)
    • 弗雷德
    • 威尔玛
    • 阿奇
    • 伊迪丝

    在引用出现之前,平面键值哈希是我们能做的最好的,但引用允许

    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",
        },
    );
    

    在内部,%personal_info 的键和值都是标量,但值是一种特殊的标量:散列引用,由 {} 创建.这些引用允许我们模拟多维"哈希.例如,我们可以通过

    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}
    

    注意Perl允许我们省略下标之间的箭头,所以上面等价于

    Note that Perl allows us to omit arrows between subscripts, so the above is equivalent to

    $personal_info{Flintstone}{SPOUSE}
    

    如果您想了解有关 Fred 的更多信息,需要输入大量内容,因此您可能会像光标一样获取参考:

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

    因为上面代码片段中的 $fred 是一个 hashref,所以箭头是必需的.如果您忽略它但明智地启用use strict 来帮助您捕获此类错误,编译器会抱怨:

    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 引用类似于 C 和 C++ 中的指针,但它们永远不能为空.C 和 C++ 中的指针需要取消引用,Perl 中的引用也是如此.

    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 和 C++ 函数参数具有按值传递语义:它们只是副本,因此修改不会返回给调用者.如果你想看到变化,你必须传递一个指针.您可以通过 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;
    

    如果没有反斜杠,add_barney 会得到一个副本,一旦 sub 返回,它就会被扔掉.

    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.

    这篇关于Perl 中的散列和散列引用有什么区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆