65

我想正确理解 Perl 中的哈希。我不得不断断续续地使用 Perl 很长一段时间,而且大多数时候我需要这样做,它主要与文本处理有关。

每次,我都必须处理哈希,它会变得一团糟。我发现哈希的语法非常神秘

非常感谢对散列和散列引用、它们的区别、何时需要它们等的一个很好的解释。

4

4 回答 4

91

一个简单的散列接近于一个数组。他们的初始化甚至看起来很相似。首先是数组:

@last_name = (
  "Ward",   "Cleaver",
  "Fred",   "Flintstone",
  "Archie", "Bunker"
);

现在让我们用散列(又名关联数组)来表示相同的信息:

%last_name = (
  "Ward",   "Cleaver",
  "Fred",   "Flintstone",
  "Archie", "Bunker"
);

尽管它们具有相同的名称,但数组@last_name和哈希%last_name是完全独立的。

使用数组,如果我们想知道 Archie 的姓氏,我们必须执行线性搜索:

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

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

print "Archie $last_name{Archie}\n";

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

  • 切肉刀(姓氏)
    • 病房(名字)
    • 六月(配偶的名字)
  • 打火石
    • 弗雷德
    • 威尔玛
  • 掩体
    • 阿奇
    • 伊迪丝

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

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};
print "Fred's wife is $fred->{SPOUSE}\n";

因为$fred在上面的代码片段中是一个 hashref,所以箭头是必要的。如果您将其省略但明智地启用use strict以帮助您捕获这些类型的错误,编译器将抱怨:

Global symbol "%fred" requires explicit package name at ...

Perl 引用类似于 C 和 C++ 中的指针,但它们永远不能为空。C 和 C++ 中的指针需要取消引用,Perl 中的引用也是如此。

C 和 C++ 函数参数具有按值传递的语义:它们只是副本,因此修改不会返回给调用者。如果要查看更改,则必须传递一个指针。您可以通过 Perl 中的引用获得此效果:

sub add_barney {
    my($personal_info) = @_;

    $personal_info->{Rubble} = {
        FIRST  => "Barney",
        SPOUSE => "Betty",
    };
}

add_barney \%personal_info;

如果没有反斜杠,add_barney则会得到一个副本,该副本会在子返回后立即被丢弃。

还要注意上面“胖逗号”( =>) 的使用。它自动引用左侧的字符串,并使哈希初始化在语法上不那么嘈杂。

于 2009-11-30T02:38:14.690 回答
16

下面演示了如何使用散列和散列引用:

my %hash = (
    toy    => 'aeroplane',
    colour => 'blue',
);
print "I have an ", $hash{toy}, " which is coloured ", $hash{colour}, "\n";

my $hashref = \%hash;
print "I have an ", $hashref->{toy}, " which is coloured ", $hashref->{colour}, "\n";

另请参阅perldoc perldsc

于 2009-11-30T02:34:58.503 回答
10

哈希是 Perl 中的一种基本数据类型。它使用密钥来访问其内容。

哈希引用是对哈希引用的缩写。引用是标量,即简单值。它是一个标量值,本质上包含一个指向实际哈希本身的指针。

链接:perl 中 hash 和 hash ref 的区别 - Ubuntu Forums

删除的语法也有所不同。与 C 一样,perl 对哈希的工作方式如下:

delete $hash{$key};

和哈希引用

delete $hash_ref->{$key};

Perl Hash Howto是了解 Hash 与 Hash with Hash References 的绝佳资源

这里还有另一个链接,其中包含有关 perl 和参考的更多信息

于 2009-11-30T01:07:14.723 回答
7

请参阅perldoc perlreftut,它也可以在您自己计算机的命令行上访问。

引用是一个标量值,它引用整个数组或整个哈希(或几乎任何其他内容)。名称是您已经熟悉的一种参考。想想美国总统:一袋乱七八糟的血和骨头。但是要谈论他,或者在计算机程序中表示他,您所需要的只是简单、方便的标量字符串“Barack Obama”。

Perl 中的引用类似于数组和散列的名称。它们是 Perl 的私有内部名称,因此您可以确定它们是明确的。与“巴拉克奥巴马”不同,引用只指一件事,你总是知道它指的是什么。如果你有一个数组的引用,你可以从中恢复整个数组。如果您有对哈希的引用,则可以恢复整个哈希。但参考仍然是一个简单、紧凑的标量值。

于 2009-11-30T01:25:06.860 回答