在 Lisp 中将哈希表中的每个值重置为 nil
Reset each value in hashtable to nil in Lisp
此函数使用 putp 将每个指定词性的值重置为 NIL。
第一个参数是一个散列table,对于这个例子,我们称它为word-dict.
传递给 resetPartsOfSpeech 的词性数量是可变的。
示例:
(resetPartsOfSpeech word-dict 'subject 'verb 'prep 'directObj)
(defun resetPartsOfSpeech(word-dict &rest parts)
(do ((partsVar parts (cdr partsVar)))
( (null partsVar) T)
;;; procces the car
(putp NIL word-dict (car partsVar))
))
; here is the results of the function
#S(HASH-TABLE :TEST FASTHASH-EQL (NIL . VERB) (LICKED . VERB) (HAS . VERB) (ATE . VERB) (RAN . VERB) (TAUGHT . VERB)
如您所见,它只是将 NIL 变量添加到列表中,并没有将它们全部清除。
我有的辅助函数,这两个函数的工作是从创建的散列table中放入和获取数据。
; creating the hash table
(setf word-dict (MAKE-HASH-TABLE))
(defun putp (symbol ht value)
(if (ATOM symbol)
(setf (gethash symbol ht) value)
(ERROR "~s is not a valid symbol for putp" symbol)
))
(defun getp (symbol ht)
(gethash symbol ht) )
(defun isa(word partOfSpeech) ; this function returns T if the specified word is that specified partOfSpeech,
; otherwise, NIL is returned.
(eql (getp word word-dict) partOfSpeech))
(defun set_isa (partOfSpeech &rest words) ; this function defines each
word in the list of words to the specified partOfSpeech
;在字典中(硬编码单词词典)。
(做((wordVar 词(cdr wordVar))))
( (NULL wordVar ) T)
;;;处理 CAR
(putp (car wordVar) word-dict partOfSpeech)
(print (car wordVar))))
我无法理解的是我应该如何遍历哈希 table 中的每个值。我正在考虑的是做一个嵌套的 do 或 dolist 循环,但不能完全弄清楚如何使用 table 中的值来实现它,或者如果这可能的话。
根本问题在于:
(putp NIL word-dict (car partsVar))
调用putp
时,nil
绑定symbol
,word-dict
绑定ht
,(car partsVar)
,即词性列表中的下一个符号绑定到 value
。在 putp
表达式中:
(setf (gethash symbol ht) value)
变为:
(setf (gethash 'nil word-dict) (car partsVar))
这里,(gethash 'nil word-dict)
是处设置为值(car partsVar)
。由于散列 table 中还没有 'nil
键,因此创建了一个新键并赋予值 (car partsVar)
,在 OP 示例中为 'verb
。
在原始的 putp
表达式中,(car partsVal)
应该在 symbol
位置,因为这是应该更新的键:
(defun resetPartsOfSpeech (word-dict &rest parts)
(do ((partsVar parts (cdr partsVar)))
((null partsVar) t)
(putp (car partsVar) word-dict 'nil)))
虽然这样解决了问题,但还有更好的解决办法。
(defun reset-parts-of-speech (word-dict &rest parts)
(dolist (part parts)
(putp part word-dict 'nil)))
当您想对元素列表进行简单迭代时,在本例中为词性符号,只需使用简单的 dolist
。此外,最好在 Lisp 风格方面养成更好的习惯。喜欢烤肉串而不是骆驼盒;将所有右括号放在一行中(几乎总是);使用适当的缩进使程序结构清晰。一个好的 lisp-aware 文本编辑器对最后两个最有帮助。
这是在 REPL 中使用基于 :
的 set-isa
函数进行的一些测试
SCRATCH> (defvar *word-dict* (make-hash-table))
*WORD-DICT*
SCRATCH> (set-isa 'verb 'eat 'sleep 'walk)
NIL
SCRATCH> (set-isa 'noun 'cake 'ice-cream 'pizza)
NIL
SCRATCH> (gethash 'verb *word-dict*)
(WALK SLEEP EAT)
T
SCRATCH> (gethash 'noun *word-dict*)
(PIZZA ICE-CREAM CAKE)
T
SCRATCH> (set-isa 'adjective 'delicious 'sweet 'crispy)
NIL
SCRATCH> (gethash 'adjective *word-dict*)
(CRISPY SWEET DELICIOUS)
T
SCRATCH> (resetPartsOfSpeech *word-dict* 'verb)
T
SCRATCH> (gethash 'verb *word-dict*)
NIL
T
SCRATCH> (gethash 'noun *word-dict*)
(PIZZA ICE-CREAM CAKE)
T
SCRATCH> (reset-parts-of-speech *word-dict* 'adjective 'noun)
NIL
SCRATCH> (gethash 'noun *word-dict*)
NIL
T
SCRATCH> (gethash 'adjective *word-dict*)
NIL
T
更新
以上内容基于 OP 语句:“此函数将每个指定词性的值重置为 NIL...,”这似乎表明 OP希望散列 table 将词性存储为键,将单词列表存储为关联值。这似乎也符合 。但是,在交换意见之后,OP 似乎更喜欢散列 table,其中单个单词作为键,词性作为关联值。目前还不清楚应该如何处理可能与多个词性相关联的词。
OP 示例代码 #S(HASH-TABLE :TEST FASTHASH-EQL (NIL . VERB) (LICKED . VERB) ;...,
中显示的散列 table 以及 OP 注释支持第二种解释。如果是这种情况,那么将散列 table 中的每个值“重置”为 'nil
是什么意思?也许明智的做法是完全删除具有与提供的词性参数匹配的值的每个条目。
这可以通过使用 dolist
遍历词性列表,然后使用 maphash
映射散列 table 和一个函数来轻松实现包含匹配值的条目:
(defun remove-parts-of-speech (word-dict &rest parts)
(dolist (part parts)
(maphash #'(lambda (k v) (if (eql v part) (remhash k word-dict)))
word-dict)))
这是另一个 REPL 演示,它使用 OP 的当前 set-isa
函数填充散列 table,其中包含用于键的单词和用于值的词性。在用 'noun
s、'verb
s 和 'adjectives
这九个词填充散列 table 之后,remove-parts-of-speech
函数用于删除所有条目来自 *word-dict*
的名词或动词。在此之后,散列 table.
中只剩下三个形容词条目
CL-USER> (defvar *word-dict* (make-hash-table))
*WORD-DICT*
CL-USER> (set-isa 'verb 'run 'jump 'climb)
RUN
JUMP
CLIMB
T
CL-USER> (set-isa 'noun 'hat 'shoe 'scarf)
HAT
SHOE
SCARF
T
CL-USER> (set-isa 'adjective 'salty 'spicy 'sour)
SALTY
SPICY
SOUR
T
CL-USER> *word-dict*
#<HASH-TABLE :TEST EQL :COUNT 9 {1003CE10C3}>
CL-USER> (hash-table-count *word-dict*)
9
CL-USER> (remove-parts-of-speech *word-dict* 'noun 'verb)
NIL
CL-USER> (hash-table-count *word-dict*)
3
CL-USER> (gethash 'spicy *word-dict*)
ADJECTIVE
T
此函数使用 putp 将每个指定词性的值重置为 NIL。
第一个参数是一个散列table,对于这个例子,我们称它为word-dict.
传递给 resetPartsOfSpeech 的词性数量是可变的。
示例: (resetPartsOfSpeech word-dict 'subject 'verb 'prep 'directObj)
(defun resetPartsOfSpeech(word-dict &rest parts)
(do ((partsVar parts (cdr partsVar)))
( (null partsVar) T)
;;; procces the car
(putp NIL word-dict (car partsVar))
))
; here is the results of the function
#S(HASH-TABLE :TEST FASTHASH-EQL (NIL . VERB) (LICKED . VERB) (HAS . VERB) (ATE . VERB) (RAN . VERB) (TAUGHT . VERB)
如您所见,它只是将 NIL 变量添加到列表中,并没有将它们全部清除。
我有的辅助函数,这两个函数的工作是从创建的散列table中放入和获取数据。
; creating the hash table
(setf word-dict (MAKE-HASH-TABLE))
(defun putp (symbol ht value)
(if (ATOM symbol)
(setf (gethash symbol ht) value)
(ERROR "~s is not a valid symbol for putp" symbol)
))
(defun getp (symbol ht)
(gethash symbol ht) )
(defun isa(word partOfSpeech) ; this function returns T if the specified word is that specified partOfSpeech,
; otherwise, NIL is returned.
(eql (getp word word-dict) partOfSpeech))
(defun set_isa (partOfSpeech &rest words) ; this function defines each
word in the list of words to the specified partOfSpeech
;在字典中(硬编码单词词典)。 (做((wordVar 词(cdr wordVar)))) ( (NULL wordVar ) T) ;;;处理 CAR (putp (car wordVar) word-dict partOfSpeech) (print (car wordVar))))
我无法理解的是我应该如何遍历哈希 table 中的每个值。我正在考虑的是做一个嵌套的 do 或 dolist 循环,但不能完全弄清楚如何使用 table 中的值来实现它,或者如果这可能的话。
根本问题在于:
(putp NIL word-dict (car partsVar))
调用putp
时,nil
绑定symbol
,word-dict
绑定ht
,(car partsVar)
,即词性列表中的下一个符号绑定到 value
。在 putp
表达式中:
(setf (gethash symbol ht) value)
变为:
(setf (gethash 'nil word-dict) (car partsVar))
这里,(gethash 'nil word-dict)
是处设置为值(car partsVar)
。由于散列 table 中还没有 'nil
键,因此创建了一个新键并赋予值 (car partsVar)
,在 OP 示例中为 'verb
。
在原始的 putp
表达式中,(car partsVal)
应该在 symbol
位置,因为这是应该更新的键:
(defun resetPartsOfSpeech (word-dict &rest parts)
(do ((partsVar parts (cdr partsVar)))
((null partsVar) t)
(putp (car partsVar) word-dict 'nil)))
虽然这样解决了问题,但还有更好的解决办法。
(defun reset-parts-of-speech (word-dict &rest parts)
(dolist (part parts)
(putp part word-dict 'nil)))
当您想对元素列表进行简单迭代时,在本例中为词性符号,只需使用简单的 dolist
。此外,最好在 Lisp 风格方面养成更好的习惯。喜欢烤肉串而不是骆驼盒;将所有右括号放在一行中(几乎总是);使用适当的缩进使程序结构清晰。一个好的 lisp-aware 文本编辑器对最后两个最有帮助。
这是在 REPL 中使用基于
set-isa
函数进行的一些测试
SCRATCH> (defvar *word-dict* (make-hash-table))
*WORD-DICT*
SCRATCH> (set-isa 'verb 'eat 'sleep 'walk)
NIL
SCRATCH> (set-isa 'noun 'cake 'ice-cream 'pizza)
NIL
SCRATCH> (gethash 'verb *word-dict*)
(WALK SLEEP EAT)
T
SCRATCH> (gethash 'noun *word-dict*)
(PIZZA ICE-CREAM CAKE)
T
SCRATCH> (set-isa 'adjective 'delicious 'sweet 'crispy)
NIL
SCRATCH> (gethash 'adjective *word-dict*)
(CRISPY SWEET DELICIOUS)
T
SCRATCH> (resetPartsOfSpeech *word-dict* 'verb)
T
SCRATCH> (gethash 'verb *word-dict*)
NIL
T
SCRATCH> (gethash 'noun *word-dict*)
(PIZZA ICE-CREAM CAKE)
T
SCRATCH> (reset-parts-of-speech *word-dict* 'adjective 'noun)
NIL
SCRATCH> (gethash 'noun *word-dict*)
NIL
T
SCRATCH> (gethash 'adjective *word-dict*)
NIL
T
更新
以上内容基于 OP 语句:“此函数将每个指定词性的值重置为 NIL...,”这似乎表明 OP希望散列 table 将词性存储为键,将单词列表存储为关联值。这似乎也符合
OP 示例代码 #S(HASH-TABLE :TEST FASTHASH-EQL (NIL . VERB) (LICKED . VERB) ;...,
中显示的散列 table 以及 OP 注释支持第二种解释。如果是这种情况,那么将散列 table 中的每个值“重置”为 'nil
是什么意思?也许明智的做法是完全删除具有与提供的词性参数匹配的值的每个条目。
这可以通过使用 dolist
遍历词性列表,然后使用 maphash
映射散列 table 和一个函数来轻松实现包含匹配值的条目:
(defun remove-parts-of-speech (word-dict &rest parts)
(dolist (part parts)
(maphash #'(lambda (k v) (if (eql v part) (remhash k word-dict)))
word-dict)))
这是另一个 REPL 演示,它使用 OP 的当前 set-isa
函数填充散列 table,其中包含用于键的单词和用于值的词性。在用 'noun
s、'verb
s 和 'adjectives
这九个词填充散列 table 之后,remove-parts-of-speech
函数用于删除所有条目来自 *word-dict*
的名词或动词。在此之后,散列 table.
CL-USER> (defvar *word-dict* (make-hash-table))
*WORD-DICT*
CL-USER> (set-isa 'verb 'run 'jump 'climb)
RUN
JUMP
CLIMB
T
CL-USER> (set-isa 'noun 'hat 'shoe 'scarf)
HAT
SHOE
SCARF
T
CL-USER> (set-isa 'adjective 'salty 'spicy 'sour)
SALTY
SPICY
SOUR
T
CL-USER> *word-dict*
#<HASH-TABLE :TEST EQL :COUNT 9 {1003CE10C3}>
CL-USER> (hash-table-count *word-dict*)
9
CL-USER> (remove-parts-of-speech *word-dict* 'noun 'verb)
NIL
CL-USER> (hash-table-count *word-dict*)
3
CL-USER> (gethash 'spicy *word-dict*)
ADJECTIVE
T