【perl脚本】多维HASH的一些使用总结

简介: 【perl脚本】多维HASH的一些使用总结

前言

继续今日学习~~

学会使用多维hash是我perl一级菜鸟进化成二级菜鸟的标志事件,目前等第二个标志事件已经等了一年半,还没有等到。因此我觉得还是把多维hash一些小事总结下好了。

正文

赋值

一维hash的赋值方式多种多样,而多维hash我一般就乖乖使用最基本的单点赋值方式,绝对不浪:

1. my %my_hash;
2. my $sig1 = "amod_bmod_awsize";
3. my $sig2 = "bmod_amod_bresp";
4. 
5. $my_hash{$sig1}{name}  = "amod_bmod_awsize";
6. $my_hash{$sig1}{width} = 8;
7. $my_hash{$sig1}{link}{src} = "amod";
8. $my_hash{$sig1}{link}{dst} = "bmod";
9. 
10. $my_hash{$sig2}{name}  = "bmod_amod_bresp";
11. $my_hash{$sig2}{width} = 2;
12. $my_hash{$sig2}{link}{src} = "bmod";
13. $my_hash{$sig2}{link}{dst} = "amod";
14. $my_hash{$sig2}{sel}{0} = 0;
15. $my_hash{$sig2}{sel}{2} = 2;
16. $my_hash{$sig2}{sel}{10} = 10;

当然了,多维hash一样可以跟一维一样用胖箭头赋值:

1. my %ascii_for_char = (
2.     'digit'      => {
3.         '0'  => 48,
4.         '1'  => 49,
5.     },
6.     'upper case' => {
7.         'A'  => 65,
8.         'B'  => 66,
9.     },
10.     'lower case' => {
11.         'a'  => 97,
12.         'b'  => 98,
13.     },
14. );

上面这个是我复制过来的,我自己还是喜欢把各个维度展开写,突出一个稳字。

多维hash的某一个key可能指向某一个值,也可能指向一个hash,例如上式中$my_hash{$sig2}指向一个多维hash,$my_hash{$sig2}{name}指向一个值。

而一个key是不能即指向一个值又指向一个其他的东西的,这个道理说起来太简单了,但是我之前就卯足了劲想这么用:

1. $my_hash{$sig} = "awsize";
2. $my_hash{$sig}{src} = "a";
3. $my_hash{$sig}{dst} = "b";

我当时觉得非常合理啊,我这个$sig指向一个信号名,然后下携两个子项分别是src和dst,天衣无缝非常完美的。但是呢,编译时候就在这报错,后来才想明白一个key不能有多个指向。

赋值时,$my_hash{$sig}{dst} = "b" 和  $my_hash{$sig}{"dst"} = "b"是一样的,当然%hash_A = ("key1" => value1, "key2" => value2) 和 %hash_A = (key1 => value1, key2 => value2) 也是一样的,keyx会自动被引号引起来。

打印

一维hash一般直接print %hash就够用了,而对于嵌套的多维数组呢,可以借助一个库来实现清晰的打印:

1. use Data::Dumper;
2. 
3. my %my_hash;
4. 
5. ........
6. 
7. print Dumper(\%my_hash);

打印效果不错,但还是有点美中不足(主要是递进看着难受):

所以本着有轮子还要自己造好看的轮子的原则,死心眼的写了这个函数:

1. sub display_hash{
2.  my $obj   = shift @_;
3.  my $tab_n = shift @_;
4.  my $tab   = "";
5.  my @re;
6. 
7.  $tab_n = 0 unless $tab_n;
8. 
9.  $tab = " " x $tab_n;
10.   my %hash = %$obj;
11.   for my $key(sort keys %hash){
12.     $str = $tab."$key";
13.     if(ref $hash{$key} eq "HASH"){
14.       #$str .= "\n";
15.       push(@re, $str);
16.       @re = (@re, &display_hash(\%{$hash{$key}}, $tab_n+4));
17.     } else {
18.       $str .= " => $hash{$key}";
19.       push(@re, $str);
20.     }
21.   }
22.   return @re;
23. }
24. 
25. sub display_list{
26.   my @list   = @_;
27.   for my $obj (@list){
28.     print "$obj\n";
29.   }
30. }

这样的话,打印hash就是这个效果:

&display_list(&display_hash(\%my_hash));

看着舒服了很多啊,而且可控性也高了很多,比如在里面加加颜色啥的都很方便;

使用sort时候注意,他的排序是根据首字符的,因此是0 10 2这样的顺序(即使key写成int(10)也不行),如果想通过key索引有先后顺序的value,不妨考虑使用1 11 111 1111这样做key?

数字的排序需要用$a <=> $b的写法,但是在遍历key时候应该怎么使用呢?我还没想清楚。

删除

同一维hash一样,删除一个key会将其所指向的内容全部删除:

1. delete $my_hash{bmod_amod_bresp}{width};
2. delete $my_hash{"amod_bmod_awsize"}{name};
3. 
4. &display_list(&display_hash(\%my_hash));

遍历

这样就ok了,下层hash用%{}转一下:

1. for my $obj0 (sort keys %my_hash){
2.  for my $obj1(sort keys %{$my_hash{$obj0}}){
3.    print "$obj1, $my_hash{$obj0}{$obj1} \n";
4.  }
5. }

引用

正常的$obj = \%my_hash引用就可以了,解引用也可直接%hash = %$obj,或者不解直接用$obj -> {$sig1} -> {name}这样用应该也是没问题的,不过这中花哨的写法对我来说太难了,以下三种方式都可以:

1. my $hash = \%my_hash;
2. print "hello1, $hash->{amod_bmod_awsize}->{name} \n";
3. print "hello2, $hash->{amod_bmod_awsize}{name} \n";
4. print "hello3, ${$hash}{amod_bmod_awsize}{name} \n";
1. hello1, amod_bmod_awsize 
2. hello2, amod_bmod_awsize 
3. hello3, amod_bmod_awsize

初始化

多维哈希合并时候一样是这个语法(好像这些都是废话):

%hash = (%hash1, %hash2);

因此要初始化一个多维hash和之前一样:

%hash = ();

拷贝

hash进行=直接拷贝的话,是一种深层指针拷贝,看下这个代码:

1. delete $my_hash{$sig1}; # no use, to long
2. my $sig3 = "bmod_amod_buser";
3. $my_hash{$sig3} = $my_hash{$sig2};
4. 
5. print "first, copy=====================\n";
6. &display_list(&display_hash(\%my_hash));
7. 
8. print "\nfirst, delete====================\n";
9. delete $my_hash{bmod_amod_bresp}{width};
10. &display_list(&display_hash(\%my_hash));

打印结果:

1. first, copy=====================
2. bmod_amod_bresp
3.     link
4.         dst => amod
5.         src => bmod
6.     name => bmod_amod_bresp
7.     sel
8.         0 => 0
9.         10 => 10
10.         2 => 2
11.     width => 2
12. bmod_amod_buser
13.     link
14.         dst => amod
15.         src => bmod
16.     name => bmod_amod_bresp
17.     sel
18.         0 => 0
19.         10 => 10
20.         2 => 2
21.     width => 2
22. 
23. first, delete====================
24. bmod_amod_bresp
25.     link
26.         dst => amod
27.         src => bmod
28.     name => bmod_amod_bresp
29.     sel
30.         0 => 0
31.         10 => 10
32.         2 => 2
33. bmod_amod_buser
34.     link
35.         dst => amod
36.         src => bmod
37.     name => bmod_amod_bresp
38.     sel
39.         0 => 0
40.         10 => 10
41.         2 => 2

可以发现,拷贝是吧全部信息都拷过去了,但是$sig2 width被删除时,$sig3中对应的信息也被删除了。因此需要深度复制拷贝的话,请使用:

use Clone 'clone';


相关文章
|
19天前
|
存储 索引 Python
python中的哈希表数据结构
python中的哈希表数据结构
18 0
|
19天前
|
Python
在Python中,哈希表
在Python中,哈希表
22 1
|
6月前
|
存储 缓存 数据库
Python高级数据结构——散列表(Hash Table)
Python高级数据结构——散列表(Hash Table)
80 1
Python高级数据结构——散列表(Hash Table)
|
8月前
|
存储 算法 索引
Python中的哈希表
哈希表是一种常用的数据结构,广泛应用于字典、散列表等场合。它能够在O(1)时间内进行查找、插入和删除操作,因此被广泛应用于各种算法和软件系统中。哈希表的实现基于哈希函数,将给定的输入映射到一个固定大小的表格中,每个表项存储一个关键字/值对。哈希函数是一个将任意长度的输入映射到固定长度输出的函数,通常将输入映射到从0到N-1的整数范围内。哈希函数要尽量均匀地分布输入,以避免冲突,即多个输入映射...
49 0
|
19天前
|
Perl
Perl 教程 之 Perl 哈希 12
三元运算符 ? :
21 5
|
19天前
|
Perl
|
19天前
|
Perl
|
19天前
|
Perl
Perl 教程 之 Perl 哈希 5
读取哈希的 key 和 value
14 0
|
19天前
|
Perl
|
19天前
|
Perl
Perl 教程 之 Perl 哈希 3
访问哈希元素
19 4