2009-11-30 161 views
50

我想正确理解Perl中的哈希。我不得不间歇地使用Perl一段时间,大多数时候我需要这样做,它主要与文本处理有关。我不得不处理哈希,它会变得混乱。我发现这个语法对于哈希来说非常神秘Perl中的哈希和哈希引用有什么区别?

哈希和哈希引用的一个很好的解释,它们的不同之处,当它们是需要的时候,会非常感激。

+35

_ *给你一个苹果* _假装这是一个散列。 _ *指着你向冰箱里的苹果书面指示* _这是一个散列参考。 – 2009-11-30 02:37:55

+2

你可以看看_Learning Perl_有关哈希的章节。 – 2009-11-30 07:46:45

+0

@〜庸医:我希望这是一个答案,而不是一个评论,以便我可以正确地为你提供帮助。 – 2009-11-30 13:47:54

回答

78

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

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

现在,让我们代表了一个哈希(又名关联数组)相同的信息:

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

虽然它们具有相同的名称,数组@last_name和散列%last_name是完全独立的。

与阵列,如果我们想知道阿奇的姓氏,我们必须执行线性搜索:

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 = $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会得到多数民众赞成尽快扔掉作为子返回一个副本。

还请注意使用上面的“胖逗号”(=>)。它自动引用其左侧的字符串,并使得哈希初始化的语法更少。

+0

在7年后下降,注意到C和C++允许不使用指针来传递引用。 'void f(DataType&arg)'通过引用传递'arg',并且不需要解引用来访问或修改。 – 2016-07-04 19:20:44

+0

@JimV那时候你传递一个_reference_,用'&'声明,这是一种别名。语义_is_传递值。 – zdim 2016-09-30 23:27:19

+0

一个伟大的职位:)。一个评论 - 或许一个警告提示值得注意的是'@ _'别名参数,所以一个_can_可以改变它们的子地址(散列键除外)? – zdim 2016-10-01 07:25:55

10

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

散列ref是​​对散列的引用的缩写。参考文献是 标量,这是简单的值。它基本上是 一个标量值,其实际上包含 ,它指向实际的散列本身。

链接:difference between hash and hash ref in perl - Ubuntu Forums

的差异也是在语法删除。像C,Perl的工作原理是这样的哈希值:

delete $hash{$key}; 

和哈希引用

delete $hash_ref->{$key}; 

Perl Hash Howto是一个很好的资源,了解哈希值,而使用哈希引用哈希

也有另一种链接here that has more information on perl and references

6

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

的引用是指整个阵列或整个哈希(或其它任何东西)的标量值。名称是您已经熟悉的一种参考。想想美国总统:一团混乱,不便的血与骨头。但是要谈论他,或者在计算机程序中代表他,所需要的只是简单,方便的标量字符串“Barack Obama”。

Perl中的引用就像数组和哈希的名称。它们是Perl的私有名称,所以你可以确定它们是明确的。与“巴拉克奥巴马”不同,参考只涉及一件事,而且你总是知道它是指什么。如果你有一个数组的引用,你可以从它恢复整个数组。如果你有一个散列引用,你可以恢复整个散列。但是这个参考仍然是一个简单而紧凑的标量值。

+0

@ mjp66答案的重要部分是使用'perldoc perlreftut',它与OP的计算机上'perl'一起安装。对于OP所使用的特定版本的perl *而言,这总是最准确的文档。链接仅包含在礼貌中。因此,从这个意义上说,Perl文档URL就像引用。链接中的内容可能会更改,但链接始终指向“Perl参考教程”。并非所有链接都是平等的。仅供参考。 – 2016-03-05 17:02:38

15

下面演示了如何使用哈希和哈希参考:

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

+8

就我个人而言,我发现看到术语'%hash'来描述一个哈希值时会感到困惑。将'%hash'重新标记为'%favorite'可能是一个好主意,只是为了将这一点引入家庭。然后print语句就像'print'一样我最喜欢的玩具是$ favorite {toy}“;' – Zaid 2009-11-30 03:26:42