我有两个元素和一个列表。我必须在第一个元素之前插入第二个元素,每次出现第一个元素时,在给定列表的第一个级别中。
递归版:
(defun INSERT-ELEM (E1 E2 L)
(cond ((null L) NIL)
((equal E1 (car L)) (cons E2 (INSERT-ELEM E1 E2 (cdr L))))
((equal E2 (car L)) (cons E1 (INSERT-ELEM E1 E2 (cdr L))))
(t (cons (car L) (INSERT-ELEM E1 E2 (cdr L))))))
但有些事情是错误的,它改变了地方而不是在E1前面插入E2。 有人能帮助我吗?
答案 0 :(得分:3)
有两个问题。
首先,您只应在E2
之前插入E1
。但是这句话:
((equal E2 (car L)) (cons E1 (INSERT-ELEM E1 E2 (cdr L))))
在E1
之前插入E2
。你应该删除它。
第二个问题是,当您进行递归调用时,您不会在结果中包含当前元素。因此,您要删除所有E1
元素。将递归调用更改为:
(list* e2 (car l) (insert-elem e1 e2 (cdr l)))
工作版本是:
(defun insert-elem (e1 e2 l)
(cond ((null l) nil)
((equal e1 (car l)) (list* e2 (car l) (insert-elem e1 e2 (cdr l))))
(t (cons (car l) (insert-elem e1 e2 (cdr l))))))
(insert-elem 'a 'b '(1 2 3 a c b d a b e))
=> (1 2 3 b a c b d b a b e)
答案 1 :(得分:2)
LOOP
变体,用于比较:
(defun insert-before (e1 e2 list)
(loop
for e in list
when (equalp e e1)
collect e2
collect e))
(insert-before 1 0 '(5 4 1 2 1 3 5 1 1 2 3 5 7))
=> (5 4 0 1 2 0 1 3 5 0 1 0 1 2 3 5 7)
MAPCAN
变体,为了好玩:
(defun insert-before (e1 e2 list)
(mapcan (lambda (e)
(if (equalp e e1)
(list e2 e1)
(list e)))
list))