Common Lisp 中的哈希表是用于存储关联数据的数据结构。它们把键(可以是任何对象)映射到值(可以是任何对象)。其他语言可能把这一概念称为映射、字典或哈希。
哈希表可以用make-hash-table函数创建。
(make-hash-table) ; => #<HASH-TABLE :TEST EQL :COUNT 0 {10024AD2B3}>
(注意,哈希表的打印形式取决于具体实现,所以在你的 REPL 中显示的样子可能不同。)
要从哈希表中按键获取一个值,可以使用gethash函数:
*h* ; => #<HASH-TABLE :TEST EQL :COUNT 3 {10024AD2B3}>`
(gethash :foo *h*) ; => :bar
; T
gethash会返回多个值,这将在另一个概念中讲解。
要向哈希表中插入一个值,可以像这样把setf和gethash一起使用:
(setf (gethash :foo *hash-table*) :bar) : => :bar
这会把哈希表*hash-table*中键:foo的值修改为:bar。它还会返回该值。
setf的用法将在另一个概念中讲解。
Lamont 是一个 Lisp 外星人,想自己写一款电子游戏。他请你帮忙做的一件事,就是记录一份高分榜。
定义一个函数make-high-score-table,它不接受任何实参,求值结果是一个新的空哈希表:
(make-high-score-table) ; => #<HASH-TABLE :TEST EQL :COUNT 0 {1005A90103}>
要向表中添加玩家,请定义一个函数add-player,它接受两个实参:
把玩家的初始分数设为 0。
(add-player hash-table :louis) ; => 0
(add-player hash-table :lilly) ; => 0
要为玩家设置分数,请定义一个函数set-score,它接受三个实参:
(set-score hash-table :louis 1234) ; => 1234
要从表中获取某位玩家的分数,请定义一个函数get-score,它接受两个实参:
这个函数的求值结果应该是为该玩家存储的分数。
如果该玩家没有存储分数,或者该玩家还不在表中,则求值为0。
(get-score hash-table :louis) ; => 1234
(get-score hash-table :lilly) ; => 0
(get-score hash-table :not-a-character-in-this-story) ; => 0
要从高分表中移除玩家,请定义一个函数remove-player,它接受两个实参:
对于玩家尚未添加到表中的情况,这个函数也应该能妥善处理。 显然,移除玩家之后再从表中获取他的分数,得到的就是 0。
(set-score hash-table :louis 1234) ; => 1234
(remove-player hash-table :louis) ; => T
(get-score hash-table :louis) ; => 0
(remove-player hash-table :not-in-the-table) ; => NIL