如何将值推送到散列中的现有列表 table

How to PUSH a value into an existing list within a hash table

我正在尝试编写一个将数据添加到散列中的函数 table。该函数接受一个键和一个值。如果给定键已存在于 table 中,则给定值将附加到与该键关联的现有值。如果键在 table 中尚不存在,则将该值放入列表中并添加到 table 中。这是实现:

(defparameter *ht* (make-hash-table))

(defun add-to-table (key value)
  (multiple-value-bind (existing-values present-p) (gethash key *ht*)
    (if present-p
      (push value existing-values)
      (setf (gethash key *ht*) (list value)))))

我试过这样使用函数:

(add-to-table 'company "Acme")
(add-to-table 'company "Ajax")

然而,(length (gethash 'company *ht*)) returns 1 而不是 2,尽管我添加了两家公司。这是为什么?

我发现我可以通过将 (push value existing-values) 替换为 (push value (gethash key *ht*)) 来解决问题。为什么我已经获取了它的值(existing-values),还需要使用另一个(gethash key *ht*)existing-values 不应该是某种指向列表的指针吗?

当你按下 existing-values 时,你只修改局部变量。

您可以通过以单一形式使用 place 魔法来更简单地完成此操作:

(defun add-to-table (key value)
  (push value (gethash key *ht* nil)))

这将 gethash 链和列表访问视为 一个地方,因此推送在这两种情况下都有效。

您可以通过首先确保 hash-table 条目的存在来明确表达这一点:

(defun add-to-table (key value)
  (unless (nth-value 1 (gethash key *ht*))
    (setf (gethash key *ht*) ()))
  (push value (gethash key *ht*)))

另请参阅 alexandria 实用程序库中的 ensure-gethash 以获得更通用的构造。