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

前言

继续今日学习~~

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

正文

赋值

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

my %my_hash;
my $sig1 = "amod_bmod_awsize";
my $sig2 = "bmod_amod_bresp";

$my_hash{$sig1}{name}  = "amod_bmod_awsize";
$my_hash{$sig1}{width} = 8;
$my_hash{$sig1}{link}{src} = "amod";
$my_hash{$sig1}{link}{dst} = "bmod";

$my_hash{$sig2}{name}  = "bmod_amod_bresp";
$my_hash{$sig2}{width} = 2;
$my_hash{$sig2}{link}{src} = "bmod";
$my_hash{$sig2}{link}{dst} = "amod";
$my_hash{$sig2}{sel}{0} = 0;
$my_hash{$sig2}{sel}{2} = 2;
$my_hash{$sig2}{sel}{10} = 10;

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

my %ascii_for_char = (
    'digit'      => {
        '0'  => 48,
        '1'  => 49,
    },
    'upper case' => {
        'A'  => 65,
        'B'  => 66,
    },
    'lower case' => {
        'a'  => 97,
        'b'  => 98,
    },
);

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

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

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

$my_hash{$sig} = "awsize";
$my_hash{$sig}{src} = "a";
$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就够用了,而对于嵌套的多维数组呢,可以借助一个库来实现清晰的打印:

use Data::Dumper;

my %my_hash;

........

print Dumper(\%my_hash);

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

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

sub display_hash{
	my $obj   = shift @_;
	my $tab_n = shift @_;
	my $tab   = "";
	my @re;
	
	$tab_n = 0 unless $tab_n;
	
	$tab = " " x $tab_n;
	my %hash = %$obj;
	for my $key(sort keys %hash){
		$str = $tab."$key";
		if(ref $hash{$key} eq "HASH"){
			#$str .= "\n";
			push(@re, $str);
			@re = (@re, &display_hash(\%{$hash{$key}}, $tab_n+4));
		} else {
			$str .= " => $hash{$key}";
			push(@re, $str);
		}
	}
	return @re;
}

sub display_list{
	my @list   = @_;
	for my $obj (@list){
		print "$obj\n";
	}
}

这样的话,打印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会将其所指向的内容全部删除:

delete $my_hash{bmod_amod_bresp}{width};
delete $my_hash{"amod_bmod_awsize"}{name};

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

遍历

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

for my $obj0 (sort keys %my_hash){
	for my $obj1(sort keys %{$my_hash{$obj0}}){
		print "$obj1, $my_hash{$obj0}{$obj1} \n";
	}
}

引用

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

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

初始化

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

%hash = (%hash1, %hash2);

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

%hash = ();

拷贝

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

delete $my_hash{$sig1}; # no use, to long
my $sig3 = "bmod_amod_buser";
$my_hash{$sig3} = $my_hash{$sig2};

print "first, copy=====================\n";
&display_list(&display_hash(\%my_hash));

print "\nfirst, delete====================\n";
delete $my_hash{bmod_amod_bresp}{width};
&display_list(&display_hash(\%my_hash));

打印结果:

first, copy=====================
bmod_amod_bresp
    link
        dst => amod
        src => bmod
    name => bmod_amod_bresp
    sel
        0 => 0
        10 => 10
        2 => 2
    width => 2
bmod_amod_buser
    link
        dst => amod
        src => bmod
    name => bmod_amod_bresp
    sel
        0 => 0
        10 => 10
        2 => 2
    width => 2

first, delete====================
bmod_amod_bresp
    link
        dst => amod
        src => bmod
    name => bmod_amod_bresp
    sel
        0 => 0
        10 => 10
        2 => 2
bmod_amod_buser
    link
        dst => amod
        src => bmod
    name => bmod_amod_bresp
    sel
        0 => 0
        10 => 10
        2 => 2

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

use Clone 'clone';

 

  • 3
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

尼德兰的喵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值