这里是 LISP 的初学者。我正在为即将到来的 LISP 考试做准备,我遇到了一个我无法解决的问题,所以我希望更有经验的人可以帮助我。
无论如何,这是我的问题: 您将获得一个列表,其中可能包含列表作为元素。您的任务是删除给定位置的原子元素。
列表和位置作为输入参数给出。
示例:Position=5 , List=(1 (2 3) ((4)) (5 (6))) ,应该返回 (1 (2 3) ((4)) ((6)))。
这是我到目前为止得到的...(PS 由于 imMaw 的帮助,下面的代码可以工作,您可以检查编辑以查看我之前的错误)。
(defun number_of_atoms(List)
(atoms List 0)
)
(defun atoms(List Number)
(cond
((null List) Number)
((atom (car List)) (atoms (cdr List) (+ 1 Number)))
((+ (atoms (car List) Number) (atoms (cdr List) 0)))
)
)
(defun deleteElement(Pos List)
(deleteElementAcc Pos 1 List)
)
(defun deleteElementAcc(Pos CurrPos List)
(cond
((null List) nil)
((and (atom (car List)) (not(eql CurrPos Pos))) (cons (car List) (deleteElementAcc Pos (+ CurrPos 1) (cdr List))))
((and (atom (car List)) (eql CurrPos Pos)) (deleteElementAcc Pos (+ CurrPos 1) (cdr List)))
((cons (deleteElementAcc Pos CurrPos (car List))
(deleteElementAcc Pos (+ CurrPos (number_of_atoms(car List))) (cdr List))))
)
)
最佳答案
为什么在一半的地方用 z 拼写 Pos 和 CurrPos?
而你的代码中的问题在于 cond 的最后一个分支。在List的cdr上递归时,CurrPos需要提前(car List)中的元素个数。而一个简单的(长度列表)是行不通的,因为它需要递归地计算子列表中的元素。
编辑:更多细节 假设我们打电话
(deleteElement 3 '((1 2) (3 4)))
你把它变成
(deleteElementPos 3 1 '((1 2) (3 4))),
它落入 cond 的最后一个 case,你得到 p>
(cons (deleteElementAcc 3 1 '(1 2))
(deleteElementAcc 3 1 '((3 4))))
注意 currPos 对于列表的 cdr 是错误的 - 它应该是 3,而不是 1。你实际上希望你的代码变成
(cons (deleteElementAcc 3 1 '(1 2))
(deleteElementAcc 3 (+ 1 2) '((3 4))))
因为 (car List) 中有 2 个元素。
所以,你只需要改变
(deleteElementAcc Pos CurrPos (cdr List))
进入
(deleteElementAcc Pos (+ CurrPos (recursive-length (car List))) (cdr List))
和程序递归长度,这是一个非常简单的函数。它应该计算子列表中的元素,例如 (recursive-length '((1 2) ((3)))) 返回 3。
关于lisp - 删除列表中包含列表的元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13612960/