哈希

哈希是使Perl 语言称为杰出编程语言的关键特色.哈希类似于Java 中的map 类型, 存储的是 key-value 键值对. perl 的哈希是非常高效的, 当hash 的元素有很多时, 查询也是相当快的.

1. 哈希特性

哈希结构存储的是一组 key-value 对的集合. 其中key 为字符串, value 为直接量, 可以通过key 来获取value 的值.

哈希和数组比较相似, 只不过数组是通过数字索引来获取元素的值, 哈希是通过字符串key来获取..

  • 哈希是无序的
  • 哈希的key不能重复, 适合存储一对一, 多对一的关系
  • 哈希中可以存储无限多的key-value 对
  • 哈希拥有非常高效的算法以保证在哈希元素增多时, 查询速度依然很快
  • 哈希可以同时获取多个key的值
  • 哈希value还能是单个单数, 即为字符串, 数字, 不能为数组,列表或哈希.

2. 哈希基本操作

2.1 哈希创建

  • 哈希变量命名: %+变量名, 如: %ip_hash
  • 创建哈希时, 在key的不产生歧义的情况下引号可用省略
  • 通常在创建哈希的时候, 会同时为哈希赋值, 有以下几种方式:
#1. 使用列表创建, 必须为偶数个元素, 奇数为key, 偶数为value
%hash_name= (key1, value1, key2, value2 ...);

#2. 胖箭头创建
%hash_name= (
    key1 => value1, 
    key2 => value2,
    ...,
);

#3. 用哈希为哈希复制
%hash_reverse = reverse %hash_name;

#4. 元素赋值, 如果hash_name不存在, 则会创建一个新的全局哈希变量
$hash_name{key} = value;

#5. 创建一个空的哈希,或清空哈希元素
%hash_name = ();

2.2 哈希引用

  • 哈希元素也是单一的元素, 所以引用的时候也是使用$, 和数组不同的时, 后面跟{}而不是[]
哈希赋值 语法格式
整体引用 %hash_name
单个元素引用 $hash_name{key}

2.3 哈希元素提取

可以通过@符号提取哈希中的多个元素为数组, 因为提取的为多个元素,所以用的是@而不是$.

  • 提取为数组: @array=@hash_name{key1, key2 ..};
  • 提取为列表: ($value1, $value2...) = @hash_name(key1, key2 ...);

2.4 字符串内插

  • 哈希本身不支持元素内插, 但是哈希元素支持遍历内插, 比如: "$hash_name{key}"
  • 哈希整体不支持字符串内插, 但是可以先将哈希转换为数组,然后使用数组内插,转换方式:@arrays=%hash_nane;

2.5 哈希上下文

  • perl 的数组是非常智能的, 能够揣摩你的代码上下文, 给你不同的返回
  • 上下文是指,根据左侧变量类型,使用数组做不同的赋值.
哈希赋值 示例 描述
哈希上下文 %hash1=%hash_name; 等号左边为哈希变量,则表示哈希复制
数组上下文 @hashs=%hash_name; 等号左边为数组,则表示转换哈希为数组

3. 哈希遍历

3.1 while-each 遍历

  • 遍历结果是随机的, 因为hash 本事就是无序的
while(my ($key, $val) = each %ips_hash){
    print "$key --> $val \n";
}

3.2 keys 数组遍历

  • 通过获取哈希的keys 列表进行遍历,可以进行有序遍历, 由于数组有很多遍历方式, 这样会衍生出很多遍历方式
# 获取哈希的keys 数组进行无序遍历
foreach (keys %ip_hash){
    print "$_ --> $bookMap{$_}\n";
}

# 获取哈希的keys 数组进行有序遍历
foreach (sort keys %ip_hash){
    print "$_ --> $bookMap{$_}\n";
}

3.3 keys-values 遍历

  • 单独获取哈希的keys 和 values 是无序的 ,且不能保证以一对应
  • 连续获取哈希的keys 和 values 可以保证相同索引的key 和 value 是一一对应的.
# 依次获取哈希的keys 和 values
@keys = keys %hash_name;
@values = keys %hash_name;

for my $idx ( 0..$#keys){
    print "$keys[$idx] --> $values{$idx}\n";
}

3.4 哈希转换为数组遍历

  • 创建哈希时可以由数组转换为哈希, 而数组支持字符串内插, 因此我们可以将哈希先转换为数组, 然后使用数组字符串内插来输出整个哈希
@hashs = %hash_name;
print "@hashs \n";

4. 常用方法

  • 单独使用keys 和 vlaues 返回的数组是无序的, 因此返回的元素并不一定是一一对应的. 当使用完keys 之后马上使用values , 那么此时相同索引的key 和 value是一一对应的
  • 使用reverse 的时候需要注意, 需要保证value 也是唯一的, 否则会相同的value作为key时, 会随机覆盖,变成不可控.
哈希赋值 语法格式 示例
keys 获取哈希所有的key,返回由key组成的数组 @keys = keys %hash_name;
values 获取哈希所有的value, 返回由value组成的数组 @values = values %hash_name
exists 判断key 是否在哈希中存在, 存在返回1,否则返回空 exists %hash_name{key}
delete 删除哈希中的元素,返回删除key对应的value $value = delete $hash_name{key}
reverse 颠倒哈希的key,value, 变成value-key 组合 %hash_reverse = reverse %hash

5. 内置哈希

  • perl 语言内置了哈希%ENV, 此哈希存储了当前系统的环境变量,可通过ENV 获取当前环境变量设置的key-value信息, 如: PATH: $ENV{PATH}; JAVA_HOME: $ENV{JAVA_HOME};

6. 测试用例

6.1 测试脚本

#!/usr/bin/perl

print "\n####################  2.1 创建哈希  ####################i \n";
# 1.列表创建
%char_hs = ( A, 'a', B, 'b', C, 'c');

## 2.胖箭头创建
%ip_hs = (
  "www.taobao.com" => "60.28.242.249",
  "www.baidu.com" => "61.135.169.125",
);

## 3. 使用哈希创建哈希
%ip_reverse = reverse %ip_hs;

## 4. 创建空的hash
#%null_hs = ();

## 5. 哈希元素创建
$book_hash{"java"} = "Think in java ";

print "\n####################  2.2 哈希引用  ####################\n";
# 1. 整体引用
%char_hs2 = %char_hs;

# 2. 元素引用
$char_A = $char_hs{A};
print "char_A:$char_A \n";

print "\n####################  2.3 哈希元素提取  ####################\n";
# 提取为数组
@char_array = @char_hs{A, C};
print "char_array: @char_array \n";

# 提取为列表, 为多个标量赋值
($char_B, $char_C) = @char_hs{A, C};
print "char_B: $char_B, char_C: $char_C \n";

print "\n####################  2.4 哈希元素字符串内插  ####################\n";
print "char_A:$char_A, char_B: $char_B, char_C: $char_C \n";

print "\n####################  3.1 while-each 遍历  ####################\n";
print "while-each 无序遍历 ip_hash: \n";
while (my ($key, $val) = each %ip_hs) {
    print "$key -> $val \n";
}

print "\n####################  3.2 foreach 遍历  ####################\n";
print "foreach 有序遍历 char_hs: \n";
foreach (sort keys %char_hs){
   print "$_ -> $char_hs{$_} \n";
}

print "\n####################  3.3 keys-values 遍历  ####################\n";
@keys = keys %char_hs;
@values = values %char_hs;

for my $idx (0..$#keys) {
   print "$keys[$idx] -> $values[$idx] \n";
}

print "\n####################  3.4 哈希转换为数组遍历  ####################\n";
# 哈希转换为数组
@arrays = %ip_hs;
print "arrays: @arrays \n";

print "\n####################  4. 常用方法  ####################\n";
# keys
@keys1 = keys %char_hs;
@keys2 = keys %char_hs;
print "char_hs keys: @keys1 \n";
print "char_hs keys: @keys2 \n";

# exists
$c = exists $char_hs{C};
$d = exists $char_hs{D};
print "exists: c:$c, d:$d \n";

# delete 
$del = delete $char_hs{B};
@keys = keys %char_hs;
print "delete: B -> $del, left: @keys \n";

# reverse
%r_ip_hs = reverse %ip_hs;
print "reverse: r_ip_hs \n";
while (my ($key, $val) = each %r_ip_hs) {
    print "$key -> $val \n";
}

#哈希数量
$length = keys %char_hs;
print "char_hs length: $length \n";

# 清空
%char_hs = ();
$length = keys %char_hs;
print "length after empty: $length \n";


print "\n####################  5. 内置哈希  ####################\n";
$JAVA_HOME = $ENV{JAVA_HOME};
$PATH = $ENV{PATH};
print "ENV: JAVA_HOME=$JAVA_HOME, PATH=$PATH \n";

6.2 脚本输出

[admin@localhost perl]$ ./hash.pl 

####################  2.1 创建哈希  ####################i 

####################  2.2 哈希引用  ####################
char_A:a 

####################  2.3 哈希元素提取  ####################
char_array: a c 
char_B: a, char_C: c 

####################  2.4 哈希元素字符串内插  ####################
char_A:a, char_B: a, char_C: c 

####################  3.1 while-each 遍历  ####################
while-each 无序遍历 ip_hash: 
www.taobao.com -> 60.28.242.249 
www.baidu.com -> 61.135.169.125 

####################  3.2 foreach 遍历  ####################
foreach 有序遍历 char_hs: 
A -> a 
B -> b 
C -> c 

####################  3.3 keys-values 遍历  ####################
A -> a 
C -> c 
B -> b 

####################  3.4 哈希转换为数组遍历  ####################
arrays: www.taobao.com 60.28.242.249 www.baidu.com 61.135.169.125 

####################  4. 常用方法  ####################
char_hs keys: A C B 
char_hs keys: A C B 
exists: c:1, d: 
delete: B -> b, left: A C 
reverse: r_ip_hs 
60.28.242.249 -> www.taobao.com 
61.135.169.125 -> www.baidu.com 
char_hs length: 2 
length after empty: 0 

####################  5. 内置哈希  ####################
ENV: JAVA_HOME=/opt/app/jdk/jdk1.6.0_31, PATH=/usr/lib64/qt-3.3/bin:/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/usr/perl/bin:/usr/perl/tools:/opt/app/jdk/jdk1.6.0_31/bin:/opt/app/mongo/mongodb-linux-x86_64-rhel62-3.4.2/bin:/opt/app/maven/apache-maven-2.2.1/bin:/home/admin/bin

results matching ""

    No results matching ""