我正试图在lisp中编写一个代码,以计算lisp中列表中原子的出现次数。问题是,该代码适用于除原子()
(显示为NIL
(之外的所有原子。代码中的示例:
(defun flatten (list_)
(cond ((atom list_) (list list_))
((null list_) NIL)
(t (append (flatten (car list_)) (flatten (cdr list_))) )
)
)
(defun toUniqueList (list_ out)
(cond ((null list_) NIL)
((not (member (car list_) out)) (append (list (car list_)) (toUniqueList (cdr list_) (append (list (car list_)) out)) ))
(t (toUniqueList (cdr list_) out))
)
)
(defun countOccurences (list_ x)
(cond ((null list_) 0)
((eql (car list_) x) (+ (countOccurences (cdr list_) x) 1))
(t (countOccurences (cdr list_) x))
)
)
(defun countOccurencesAll (list_)
(setq flatList (flatten list_))
(setq parsed (toUniqueList flatList '()))
(setq result '())
(dolist (x parsed)
(setq result (append result (list (list x (countOccurences flatList x)) ))))
result
)
(write (countOccurencesAll '(x y z 4.6 (a x) () (5 z x) ())))
; ((X 3) (Y 1) (Z 2) (4.6 1) (A 1) (NIL 5) (5 1))
知道如何显示()
而不是NIL
吗?
表达式nil
、'nil
、()
和'()
都被求值为nil
,CCD_9显示为nil
,除非它是一对中的cdr
,否则它将关闭列表。例如CCD_ 12被评估为CCD_。你对此无能为力。
那么问题是,因为((a) (()) (c))
真的是((a . nil) . ((nil . nil) . ((c . nil) . nil)))
,它应该将nil
/()
计数5次,还是当nil
在一对的cdr
中时忽略,只将其计数为一?
BTW在未定义的绑定上使用countOccurencesAll
中的setq
意味着您的代码由实现决定。hyperspec没有定义应该如何处理它,SBCL对它如何解释代码发出警告,其他人可能只是选择一种解释。更好的方法是使用let
来定义绑定。使用散列并在列表上迭代一次将生成O(n(解决方案。