Perl哈希数组使用
ref of hashmerge of hashes
按哈希值的大小排序(How to sort a hash of hashes by value)
hash的一些数量的判断
Checking for existence of hash subkey but creates key automatic
从文件内容构建简单hash一例
-------------------------------
ref of hash
How can I create an anonymous hash from an existing hash
my $new_hash = { %existing_hash };
Note that this solution does not make a deep copy.
I think you need to be careful here. Consider the following hash:
my %hash = (1 => 'one',2 => 'two');
There are two ways you can get a reference from this:
my $ref = \%hash;
my $anon = {%hash};
$ref is a reference to the original hash and can be used similarly to %hash. $anon is a reference to an anonymous copy of the original hash; it will have the same data but changing it won't change the original hash and vice versa.
So, for example, to start with both of these statements will have the same output
print $ref->{1},"\n";
> one
print $anon->{1},"\n";
> one
But if I change the original hash:
$hash{1} = "i";
They two print statements would output different values:
print $ref->{1},"\n";
> i
print $anon->{1},"\n";
> one
-------------------------------
merge of hashes-合并Hash数组
If you mean take the union of their data, just do:
%c = (%a, %b);
--
You can also use slices to merge one hash into another:
@a{keys %b} = values %b;
Note that items in %b will overwrite items in %a that have the same key.
--
my %c = %a;
map {$c{$_} = $b{$_}} keys %b;
--
%newHash = (%hash1, %hash2); %hash1 = %newHash;
or else ...
@hash1{keys %hash2} = values %hash2;
--
perl -MData::Dumper -le '
$x = { a => 1, b => 2 };
$y = { c => 3, d => 4 };
$x = { %$x, %$y };
print Dumper($x);'
-------------------------------
按哈希值的大小排序
How to sort a hash of hashes by value
对key进行排序
其基本的语法结构为:
sort <排序规则> <排序对象>
若要对keys进行排序则排序对象就是keys,所以最后一项要写成keys %hash。
# 按value排序
## 对hash的keys按hash value排序(按ASCII码排序)
sort { $hash{$a} cmp $hash{$b} } keys %hash
## 对hash的keys按hash value排序(按数字大小排序)
sort { $hash{$a} <=> $hash{$b} } keys %hash
# 按key排序
# 对hash的keys按hash key排序
sort {$a<=>$b} keys %hash
详见如下示例:
按key或value进行排序,原始数据如下:
my $data = {
'Ft3' => {
'Max' => '85',
'Type' => 'text',
'Position' => '17',
'Min' => '40'
},
'Ft2' => {
'Max' => '90',
'Type' => 'json',
'Position' => '11',
'Min' => '60'
},
'Ft1' => {
'Max' => '80',
'Type' => 'text',
'Position' => '19',
'Min' => '40'
},
};
先打印出key(非排序,随机)
my @keys = keys %$data;
foreach my $k (@keys){
say $k;
}
按value中的Position值排序key
$a and $b are the standard place-holders of sort. For each comparison they will hold two keys from the list. In order to compare the Position value of two elements we need to access them using $a and $b and compare the numerical(!) values using the spaceship-operator (<=>).
my @sortedab = sort { $data->{$a}{Position} <=> $data->{$b}{Position} } keys %$data;
my @sortedba = sort { $data->{$b}{Position} <=> $data->{$a}{Position} } keys %$data;
foreach my $k (@sortedab){
say $k;
}
my @maxed = sort {
$data->{$a}{Position} <=> $data->{$b}{Position}
or
$data->{$a}{Max} <=> $data->{$b}{Max}
} keys %$data;
foreach my $k (@maxed){
say $k;
}
-------------------------------
hash的一些数量的判断
问题:hash中是否有健值(k/v)对,有多少个健?
这里就有体现上下文的地方了。
if(%hash)
From perldoc perldata:
If you evaluate a hash in scalar context, it returns false if the hash is empty. If there are any key/value pairs, it returns true; more precisely, the value returned is a string consisting of the number of used buckets and the number of allocated buckets, separated by a slash.
print "Empty" if(!%hash);
print "Empty" if not(!%hash);
print "Empty" unless(%hash);
上面解决了是否有无的问题,下面来看看在'有'的情况下,有多少数量。
scalar keys %hash
or
keys %hash
my $keys = keys(%hash) ;
"$#%p"这种写法已经不再被支持了。
-------------------------------
Checking for existence of hash subkey but creates key automatic
exists looks for a hash element in a given hash. Your code is autogenerating the hash %{ $hash{output} } and checking if a hash element with key $col is existing in that hash.
if(exists $hash{output}{$col})
changed to
if(exists $hash{output} && exists $hash{output}{$col})
if(exists $hash{output} and exists $hash{output}{$col})
when you ask about the existence of $foo{bar}{fubar}, Perl automatically creates $foo{bar} in order to test whether $foo{bar}{fubar} exists. If you want to prevent this, you have to test to see if $foo{bar} exists, and if it does, then test if $foo{bar}{fubar} exists.
use v5.20;
my $hconf;
my @kwds1=('TMOUT','HISTFILESIZE');
my @kwds2=('TMOUT','HISTSIZE','HISTFILESIZE');
for my $k (@kwds1){
$hconf->{$k}->{cnt}++;
}
for my $k (@kwds2){
#这里就会自动为@kwds2中每个元素在$hconf中创建其key
say "$k\'s Cnt:$hconf->{$k}->{cnt}";
}
say 'Existed.' if exists $hconf->{'HISTSIZE'};
say 'Defined.' if defined($hconf->{'HISTSIZE'});
如果不注意自动创建hash-key,则exists或defined判断会发生误解,导致对结果的误判。
可对更多条件的综合判断来共同决定:
say 'Existed.' if exists $hconf->{'HISTSIZE'}->{cnt};
say 'Defined.' if defined($hconf->{'HISTSIZE'}->{cnt});
-------------------------------
从文件内容构建简单hash一例
use v5.20;
use Data::Dump qw(pp);
my %h;
#常规方法
#while(<DATA>){
#my ($k, $v)=split(' ', $_, 2); #ok
#my ($k, $v)=split(/\s/, $_, 2); #also ok
#$h{$k}=$v;
#}
#一句完成
#%h=map{ chomp; split /\s/, $_, 2 } <DATA>;
#map{ chomp; my ($k,$v)=split /\s+/, $_, 2; $h{$k}=$v } <DATA>;
#不想引入k,v临时变量
#map{ chomp; $h{(split /\s+/, $_, 2)[0]}=(split /\s+/, $_, 2)[1] } <DATA>;
say pp(%h);
__DATA__
11 Zhen wen jio
13 FreeOA
16 Chendu utsc
17 Jim Clark
19 Cal 2012 per
不过使用map时不是没有性能的开销代价。<DATA> 在不同上下文行为完全不一样:
1. map { ... } <DATA>
my %h = map { chomp; split /\s/, $_, 2 } <DATA>;
- <DATA> 是列表上下文:一次性把 DATA 所有行全部读到内存,存入一个数组,之后再交给 map 遍历处理。
- 内存开销:全部文本 + map 产生的 (key,val) 列表 + hash。文件行数巨大时,会一次性吃掉大量内存。
2. while(<DATA>)
while(<DATA>){
chomp;
my ($k,$v) = split /\s/, $_, 2;
$h{$k} = $v;
}
- <DATA> 是标量上下文:一次只读一行到内存,处理完这一行,该行内存就释放,再读下一行。
- 内存开销:仅当前单行 + hash 存储结果。
注意:hash 本身的存储空间两种写法都无法避免(你最终都要保存全部键值对),区别在于临时内存。
差异:map 多了「全部原始行缓存」和「map 中间列表」两块临时内存。如果大文件,并且你不需要一次性保留全部 hash:while 还可以边读边处理、丢弃不需要 key,进一步降内存;map 必须一次性读完所有行。
-------------------------------
-------------------------------
-------------------------------
-------------------------------
-------------------------------
-------------------------------