加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

Perl——哈希的创建和引用

发布时间:2020-12-16 00:03:46 所属栏目:大数据 来源:网络整理
导读:语法? 创建'引用'仅有两种方法,使用它也是两种。? 创建引用? 创建规则?1? 如果你在一个变量前加一个'/'号,你就得到了这个变量的'引用'。? ????$aref?=?/@array;?????????#?$aref?保存着指向@array的'引用'? ????$href?=?/%hash;??????????#?$href?保存着指
语法? 创建'引用'仅有两种方法,使用它也是两种。? 创建引用? 创建规则?1? 如果你在一个变量前加一个'/'号,你就得到了这个变量的'引用'。? ????$aref?=?/@array;?????????#?$aref?保存着指向@array的'引用'? ????$href?=?/%hash;??????????#?$href?保存着指向%hash的'引用'? 当你把'引用'保存在类似?$aref?或?$href的变量中,你就可以象操作其他标量一样copy或保存它。? ????$xy?=?$aref;?????????????#?$xy?现在保存了指向?@array?的'引用'? ????$p[3]?=?$href;???????????#?$p[3]?现在保存了指向?%hash?的'引用'? ????$z?=?$p[3];??????????????#?$z?现在保存了指向?%hash?的'引用'? 这些例子展示了如何创建命名变量的'引用',但是有时候,我们创建的数组或哈希没有名字。这个和你使用没有放到变量中去的字符串'/n'或数字'80'类似。? 创建规则?2? [?ITEMS?]?创建了一个新的、匿名的数组,并返回一个指向这个数组的'引用'。?{?ITEMS?}?创建了一个新的、匿名的哈希,并返回那个哈希的一个'引用'。? ????$aref?=?[?1,?"foo",?undef,?13?];??? ????#?$aref?保存了这个数组的'引用'? ????$href?=?{?APR?=>;?4,?AUG?=>;?8?};???? ????#?$href?保存了这个哈希的'引用'? 从规则?2?中得到的'引用'和从规则?1?中得到的'引用'是同一种类型的:? ????????#?这里:? ????????$aref?=?[?1,?2,?3?];? ????????#?和上面一样:? ????????@array?=?(1,?3);? ????????$aref?=?/@array;? 前面一种方法是后面两行的缩写,除了第一种方法没有创建一个多余的数组变量@array。? 如果你只是编写符号?[],?你将得到一个新的、空匿名数组。如果你使用符号?{},就能得到一个新的、空匿名哈希。? 使用引用? 当你创建了一个'引用'后,你可以对它做什么操作呢?它是标量,你可以象处理任何标量一样保存和取回它。除此之外,还有两种使用方法:? 使用规则?1? 你可以始终用一个带有大括号的数组'引用',来替换一个数组的名字。例如,用?@{$aref}?代替?@array。? 下面是一个用法的一些例子:? 数组:? ????????@a??????????????@{$aref}????????????????一个数组? ????????reverse?@a??????reverse?@{$aref}????????对一个数组做倒序排序? ????????$a[3]???????????${$aref}[3]?????????????数组中的一个成员? ????????$a[3]?=?17;?????${$aref}[3]?=?17????????对一个成员赋值? 上面每行中,两个表达式实现的是同一种功能。左边那个是对数组@a操作,右边那个是对'引用'$aref所指向的数组操作。它们对数组产生相同的作用。? 使用哈希的'引用'和数组的'引用'完全一样。? ????????%h??????????????%{$href}??????????????一个哈希? ????????keys?%h?????????keys?%{$href}?????????从哈希中将键取出来? ????????$h{'red'}???????${$href}{'red'}???????哈希中的一个成员? ????????$h{'red'}?=?17??${$href}{'red'}?=?17??对一个成员赋值? 你对一个'引用'无论想做什么,使用规则?1?已经告诉你怎么做了。?你只要象使用常规的数组或哈希一样编写Perl代码,然后把数组或哈希的名字用?{$reference}来替代。‘当我只有一个'引用'时,怎么来遍历整个数组?’你这样写:? ????????for?my?$element?(@array)?{? ???????????...? ????????}? 接着用'引用'替代数组名@array:? ????????for?my?$element?(@{$aref})?{? ???????????...? ????????}? ‘怎当我只有一个'引用'时,怎么来打印一个哈希的内容?’先写一个打印整个哈希的代码:? ????????for?my?$key?(keys?%hash)?{? ??????????print?"$key?=>;?$hash{$key}/n";? ????????}? 然后用'引用'代替那个哈希的名字:? ????????for?my?$key?(keys?%{$href})?{? ??????????print?"$key?=>;?${$href}{$key}/n";? ????????}? 使用规则?2? 使用规则?1?是你真正需要的,因为它告诉了你怎么来处理一个'引用',而它对几乎任何的'引用'都有效。但是我们通常做的事情只是和数组或哈希中的一个成员有关,使用规则?1?却是很笨重的方法,所以还有简单的方法。? ${$aref}[3]?太难阅读,所以我们这样写?$aref->[3]。? ${$href}{red}?写的太笨重,?所以我们这样写?$href->{red}。? 如果?$aref?保存的是一个数组的'引用',那么?$aref->[3]?就是这个数组的第四个成员。不要和?$aref[3]?相混淆,这个代表的是一个完全不同的数组的第四个成员,这个迷惑的数组是@aref。?变量?$aref?和?@aref?是完全不相关的,就像?$item?和?@item?一样。? 同样的,?$href->{'red'}?是哈希'引用'?的变量$href的一部分,甚至这是一个没有名字的哈希。而$href{'red'}?是另一个容易混淆的命名哈希?%href?的一部分。很容易忘记写上符号'?->',如果出现这种情况,当你的程序从一个你不想取数据的数组和哈希中取出了成员,你会得到奇怪的计算结果。? 例子? 让我们来看一个例子:? 首先,记住?[1,?3]?创建了一个匿名数组,包含了?(1,?3),然后返回一个数组的'引用'。? 现在想一下:? ????????@a?=?(?[1,?3],? ???????????????[4,?5,?6],? ???????????????[7,?8,?9]? ?????????????);? @a?是一个拥有三个成员的数组,每一个成员是另一个数组的'引用'。? $a[1]?是其中的一个'引用'。它指向一个数组,这个数组包含了(4,?6),因为这是一个数组的'引用',使用规则?2?告诉我们可以这样写?$a[1]->[2],用来取得这个数组的第三个成员。??$a[1]->[2]?值是6。?同样的,$a[0]->[1]?值是?2。这里我们就像在使用一个二维数组;你可以是用?$a[ROW]->[COLUMN]?来取得或设置数组中任何一行任何一列中的成员。? 这些符号看起来还是有些麻烦,所以还有更加简单的用法:? 箭头符号规则? 在两个下标之间的箭头是可选的。? 我们可以用这个写法$a[1][2]来代替$a[1]->[2];它们是相同的。相对于$a[0]->[1]?=?23,我们这样写$a[0][1]?=?23;它们也是相同的。? 现在它们看起来真的象二维数组了!? 你可以发现为什么箭头这么重要。没有它们,我们必须这样写${$a[1]}[2],而不是$a[1][2]。对于三维数组,它们使我们可以简单地写成$x[2][3][5]而不是写成难读的${${$x[2]}[3]}[5]方式。? --------------------------------------------------------------------------------? 解决办法? 下面是前面提出来的问题的解决方法,就是关于城市和国家名称的重新格式化。? ????1???my?%table;? ????2???while?(<>)?{? ????3????chomp;? ????4?????my?($city,?$country)?=?split?/,?/;? ????5?????$table{$country}?=?[]?unless?exists?$table{$country};? ????6?????push?@{$table{$country}},?$city;? ????7???}? ????8???foreach?$country?(sort?keys?%table)?{? ????9?????print?"$country:?";? ???10?????my?@cities?=?@{$table{$country}};? ???11?????print?join?',?',?sort?@cities;? ???12?????print?"./n";? ???13???}? 这个程序分成两部分:?第?2--7?行完成数据的输入和数据结构的创建。?第?8-13?行分析这个数据并打印报告。我们设置了一个哈希?%table,它的键是国家名称,它的健值是这个国家名称对应的城市名的数组的'引用'。这个数据结构看起来如下:? ???????????%table? ????????+-------+---+???? ????????|???????|???|???+-----------+--------+? ????????|Germany|?*---->|?Frankfurt?|?Berlin?|? ????????|???????|???|???+-----------+--------+? ????????+-------+---+? ????????|???????|???|???+----------+? ????????|Finland|?*---->|?Helsinki?|? ????????|???????|???|???+----------+? ????????+-------+---+? ????????|???????|???|???+---------+------------+----------+? ????????|??USA??|?*---->|?Chicago?|?Washington?|?New?York?|? ????????|???????|???|???+---------+------------+----------+? ????????+-------+---+? 我们先来分析输出部分。假设我们已经拥有了这个结构,那么我们怎么来输出呢?? ????8???foreach?$country?(sort?keys?%table)?{? ????9?????print?"$country:?";? ???10?????my?@cities?=?@{$table{$country}};? ???11?????print?join?',?sort?@cities;? ???12?????print?"./n";? ???13???}? %table是一个普通的哈希,我们从它这里可以取得一列键,对键进行排序,并遍历所有的键。这里唯一使用'引用'的是第10行。$table{$country}?查看了哈希中的键$country并取得它的值。这个健值是对应国家中的城市数组的'引用'。?使用规则?1?告诉我们可以通过使用?@{$table{$country}}来恢复整个数组。第10行就象? ????????@cities?=?@array;? 不同的是这里的数组的名字被'引用'?{$table{$country}}所替代。符号?@?告诉Perl去获取整个数组。得到了城市的列表后,我们照样对其进行排序,合并城市名,并打印出来。? 第2-7行负责创建数据结构,如下:? ????2???while?(<>)?{? ????3????chomp;? ????4?????my?($city,?$city;? ????7???}? 第?2-4?行获取城市和国家的名称。第5行查看这个国家名称是不是已经作为一个键存放在哈希里面了,如果没有,程序就使用符号[]?(创建规则?2)创建一个新的、空的匿名数组,同时把一个指向这个匿名数组的'引用'作为健值放到哈希里面去了。? 第6行将城市名放到对应的数组里面。$table{$country}?现在保存了一个'引用',它指向所对应的国家的城市的数组。第6行就象? ????????push?@array,?$city;? 不同的是这里的数组名被{$table{$country}}所替代。?命令?push?将城市名加到这个'引用'指向数组的最后。 这里有一个要点被我忽略了。第5行是不需要的。我们可以取掉它。? ????2???while?(<>)?{? ????3????chomp;? ????4?????my?($city,?/;? ????5???####??$table{$country}?=?[]?unless?exists?$table{$country};? ????6?????push?@{$table{$country}},?$city;? ????7???}? 如果在哈希?%table?中已经有这个国家名?$country的记录,那么,加不加第5行没有任何区别。第6行会自己定位到$table{$country}这个'引用'指向的数组,把值?$city?放到数组中去。但是如果在%table中没有那个键,比如Greece,那么它会怎么办呢?? 这是Perl,它会自己准确地完成工作。你想把一个Athens赋值给一个不存在地数组,那么Perl会帮助你创建一个新的、空的匿名数组,将它放到哈希%table里面去,然后把值?Athens?放到这个数组中。这个被称为'自动生成'?--让事物自己自动产生出来。?Perl?发现在哈希里面没有这个键,就自动地创建了一个新的哈希记录。?Perl?发现你想要使用数组作为哈希的健值,它就自动创建一个匿名的空数组,并将指向这个数组的'引用'放到那个哈希中去。一般,?Perl?创建的数组只有一个成员大小,用于保存这个新的城市名。? --------------------------------------------------------------------------------? 其他集锦? 我承诺以10%的细节来使你得到90%的好处,那就意味着我跳过了90%的知识的细节。现在来看一下其中的重要的部分,这个比阅读手册?the?perlref?manpage?要容易得多,手册讨论了100%的细节。? 手册?the?perlref?manpage中的一些集锦:? 你可以对任何东西创建'引用',包括标量,函数和其他的引用。?? 在?使用规则?1?中,当大括号里面是一个象$aref这样的标量变量时,你可以省略掉这个大括号。例如,?@$aref?和?@{$aref}是一样的,$$aref[1]?和?${$aref}[1]是一样的。?如果你是初学者,建议你还是养成加上大括号的习惯。?? 下面的操作不会copy?'引用'指向的数组:?? ????????$aref2?=?$aref1;? 你将得到两个'引用',它们都指向同一个数组。如果你修改了$aref1->[23]的值,那么你查看变量$aref2->[23]时,它也相应地变了。? 要copy这个数组,你需要这样? ????????$aref2?=?[@{$aref1}];? 使用符号?[...]?来创建一个新的匿名数组,?而且这个新的数组的'引用'被赋值给了$aref2?。?这个新的数组用'引用'$aref1所指向的数组的内容来初始化。? 同样的,要copy一个匿名哈希,你需要这样? ????????$href2?=?{%{$href1}};? 如果要判断一个变量保存的内容是不是'引用',使用函数ref?。如果它的参数是'引用',返回的值是'真'。实际上,它做得更好:如果是一个哈希的引用,它返回'HASH',如果是一个数组的引用,那么就返回'ARRAY'。?? 如果你想像字符串一样使用'引用'的话,你得到的字符串就像?? ????????ARRAY(0x80f5dec)???or????HASH(0x826afc0)? 如果看到一个像这样的字符串,你应该知道你错误地输出了一个'引用'。? 这种显示方式的另一个作用是你可以用eq来比较两个'引用',看它们是不是指向相同的东西。(你通常可以使用?==?来比较,因为它更会)? 你可以像使用'引用'一样来使用一个字符串。如果你使用"foo"作为一个数组的'引用',它就是指向数组?@foo的一个引用。这被称为'软引用'或‘符号引用?'。?使用申明?use?strict?'refs'?可以取消这个功能,如果你不小心使用了它,会导致各种可能的错误。?? 你可能更喜欢查看?the?perllol?manpage,而不是手册?the?perlref?manpage;它详细地讨论了列表的列表和多纬数组。然后,你可以继续学习手册?the?perldsc?manpage;它是数据结构的Cookbook,?它提供了处理哈希的数组,数组的哈希,以及其他数据结构的方法。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读