在Element2之前插入Element1

时间:2017-06-23 21:18:07

标签: lisp common-lisp

我有两个元素和一个列表。我必须在第一个元素之前插入第二个元素,每次出现第一个元素时,在给定列表的第一个级别中。

递归版:

(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。 有人能帮助我吗?

2 个答案:

答案 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))