其他

Zsh 开发指南(六): 哈希表

2017-11-02 作者:陌辞寒 Linux中国
哈希表是比数组更复杂的数据结构,在某些语言里被称作关联数组或者字典等等。简单说,哈希表用于存放指定键(key)对应的值(value),键和值的关系,就像字典中单词和释义的对应关系,通过单词可以快速找到释义,而不需要从头依次遍历匹配。
-- 陌辞寒


本文导航
转载自 | http://www.jianshu.com/p/0599b031a919
 作者 | 陌辞寒

导读

哈希表是比数组更复杂的数据结构,在某些语言里被称作关联数组或者字典等等。简单说,哈希表用于存放指定key对应的value,键和值的关系,就像字典中单词和释义的对应关系,通过单词可以快速找到释义,而不需要从头依次遍历匹配。准确地说,哈希表只是该功能的一种实现方式,也可以使用各种树或者其他数据结构来实现,不同的实现方式适合不同的场景,使用方法是一样的。但为了简化概念,统一使用哈希表这个名称。

哈希表定义

和其他变量类型不同,哈希表是需要提前声明的,因为哈希表的赋值语法和数组一样,如果不声明,是无法区分的。

  1. % typeset -A hashmap

  2. # 或者用 local,二者功能是一样的

  3. % local -A hashmap

  4. # 赋值的语法和数组一样,但顺序依次是键、值、键、值

  5. % hashmap=(k1 v1 k2 v2)

  6. # 直接用 echo 只能输出值

  7. % echo $hashmap

  8. v1 v2

  9. # 使用 (kv) 同时输出键和值,(kv) 会把键和值都放到同一个数组里

  10. % echo ${(kv)hashmap}

  11. k1 v1 k2 v2

  12. # 哈希表的大小是键值对的数量

  13. % echo $#hashmap

  14. 2

元素读写

读写哈希表的方法和数组类似,只是用于定位的数字变成了字符串。

  1. # 可以声明和赋值写到一行

  2. % local -A hashmap=(k1 v1 k2 v2 k3 v3)

  3. % echo $hashmap[k2]

  4. v2

  5. % hashmap[k2]="V2"

  6. # 删除元素的方法和数组不同,引号不能省略

  7. % unset "hashmap[k1]"

  8. % echo ${(kv)hashmap}

  9. k2 V2 k3 v3

哈希表拼接

  1. # 追加元素的方法和数组一样

  2. % hashmap+=(k4 v4 k5 v5)

  3. % echo $hashmap

  4. V2 v3 v4 v5

  5. % local -A hashmap1 hashmap2

  6. % hashmap1=(k1 v1 k2 v2)

  7. % hashmap2=(k2 v222 k3 v3)

  8. # 拼接哈希表,要展开成数组再追加

  9. % hashmap1+=(${(kv)hashmap2})

  10. # 如果键重复,会直接替换值,哈希表的键是不重复的

  11. % echo ${(kv)hashmap1}

  12. k1 v1 k2 v222 k3 v3

哈希表遍历

用 (kv) (k) 等先将哈希表转化成数组,然后再遍历。

  1. % local -A hashmap=(k1 v1 k2 v2 k3 v3)

  2. # 只遍历值

  3. % for i ($hashmap) {

  4. > echo $i

  5. > }

  6. v1

  7. v2

  8. v3

  9. # 只遍历键

  10. % for i (${(k)hashmap}) {

  11. > echo $i

  12. > }

  13. k1

  14. k2

  15. k3

  16. # 同时遍历键和值

  17. % for k v (${(kv)hashmap}) {

  18. > echo "$k -> $v"

  19. > }

  20. k1 -> v1

  21. k2 -> v2

  22. k3 -> v3

元素查找

判断键是否存在。

  1. % local -A hashmap=(k1 v1 k2 v2 k3 v3)

  2. % (($+hashmap[k1])) && echo good

  3. good

  4. % (($+hashmap[k4])) && echo good

如果需要判断某个值是否存在,直接对值的数组判断即可。但这样做就体现不出哈希表的优势了。

  1. % local -A hashmap=(k1 v1 k2 v2 k3 v3)

  2. # value 是值的数组,也可以用 local -a 强行声明为数组

  3. % value=($hashmap)

  4. % (( $value[(I)v1] )) && echo good

  5. good

  6. % (( $value[(I)v4] )) && echo good

元素排序

对哈希表元素排序的方法,和数组类似,多了 k v 两个选项,其余的选项如 o(升序)、O(降序)、n(按数字大小)、i(忽略大小写)等通用,不再一一举例。

  1. % local -A hashmap=(aa 33 cc 11 bb 22)

  2. # 只对值排序

  3. % echo ${(o)hashmap}

  4. 11 22 33

  5. # 只对键排序

  6. % echo ${(ok)hashmap}

  7. aa bb cc

  8. # 键值放在一起排序

  9. % echo ${(okv)hashmap}

  10. 11 22 33 aa bb cc

从字符串、文件构造哈希表

因为哈希表可以从数组构造,所以从字符串、文件构造哈希表,和数组的操作是一样的,不再一一举例。

  1. % str="k1 v1 k2 v2 k3 v3"

  2. % local -A hashmap=(${=str})

  3. % echo $hashmap

  4. v1 v2 v3

对哈希表中的每个元素统一处理

对哈希表中的每个元素统一处理,和对数组的操作是类似的,多了 k v 两个选项用于指定是对键处理还是对值处理,可以一起处理。不再一一举例。

  1. % local -A hashmap=(k1 v1 k2 v2 k3 v3)

  2. % print ${(U)hashmap}

  3. V1 V2 V3

  4. % print ${(Uk)hashmap}

  5. K1 K2 K3

  6. % print ${(Ukv)hashmap}

  7. K1 V1 K2 V2 K3 V3

:# 也可以在哈希表上用。

  1. % local -A hashmap=(k1 v1 k2 v2 k3 v3)

  2. # 排除匹配到的值

  3. % echo ${hashmap:#v1}

  4. v2 v3

  5. # 只输出匹配到的键

  6. % echo ${(Mk)hashmap:#k[1-2]}

  7. k1 k2

总结

本篇简单讲了哈希表的基本用法。篇幅不长,但因为哈希表的操作和数组类似,很多操作数组的方法都可以用作哈希表上,而且可以把键或者值单独作为数组处理,所以操作哈希表更为复杂一些。

另外还有一些更进阶的处理数组和哈希表方法,之后会讲到。

推荐文章

< 左右滑动查看相关文章 >

点击图片、输入文章 ID 或识别二维码直达



您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存