嵌套哈希表转a-list时如何确保生成点对?
解决嵌套哈希表转a-list时的点对显示问题
你遇到的其实是Common Lisp的打印规则导致的视觉误解,而非点对真的丢失了。
你的函数生成的是标准的a-list结构,当某个键对应的值是另一个a-list时,Lisp会自动简化打印格式:把(key . (alist-element1 alist-element2 ...))显示成(key alist-element1 alist-element2 ...),但底层的点对结构并没有消失。
比如你可以运行以下代码验证:
(let* ((ht (dict :session (dict :user (dict :fullname 23)))) (result (hash-table->alist* ht))) ;; 查看:SESSION对应的value (print (cdar result)) ; 输出 ((:USER (:FULLNAME . 23))) ;; 查看这个value里的第一个元素,确实是点对 (print (car (cdar result))) ; 输出 (:USER . (:FULLNAME . 23)) ;; 验证类型是点对(CONS) (print (type-of (car (cdar result)))) ; 输出 CONS )
如果你确实需要让所有层级都显式打印出点对(即使这会偏离标准a-list结构),可以修改函数,当哈希表仅包含一个键值对时,返回单个点对而非包含该点对的列表:
(defun hash-table->alist* (ht) (let ((pairs (loop for k being the hash-keys in ht using (hash-value v) collect (cons k (etypecase v (integer v) (hash-table (hash-table->alist* v))))))) ;; 如果只有一个键值对,返回单个点对,否则返回点对列表 (if (and (null (cdr pairs)) pairs) (car pairs) pairs)))
此时运行你的测试用例,会得到:
> (hash-table->alist* (dict :session (dict :user (dict :fullname 23)))) ((:SESSION . (:USER . (:FULLNAME . 23))))
注意:这种修改后的结构不再是标准a-list,因为嵌套层级的值变成了单个点对而非点对列表,可能会影响后续依赖a-list标准结构的操作,请谨慎使用。
内容的提问来源于stack exchange,提问作者Kungi
相关产品推荐
相关产品推荐

