2017-06-23 3 views
2

J'ai deux éléments et une liste. Je dois insérer le deuxième élément avant le premier élément, chaque fois que le premier élément apparaît, dans le premier niveau de la liste donnée.Insérer un élément1 avant un élément2

Version récursive:

(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)))))) 

Mais quelque chose ne va pas, il change des endroits au lieu d'insérer E2 devant E1. Quelqu'un pourrait m'aider?

+0

La ligne qui mendie ins avec '((E2' égal fait l'insertion opposée, il met' E1' avant 'E2'. – Barmar

+0

Qu'est-ce que @Barmar? Je n'ai pas compris. –

Répondre

3

Il y a deux problèmes. D'abord, vous devez seulement insérer E2 avant E1. Mais la ligne:

((equal E2 (car L)) (cons E1 (INSERT-ELEM E1 E2 (cdr L)))) 

inserts E1 avant E2 ainsi. Vous devriez enlever ça.

Le deuxième problème est que lorsque vous effectuez l'appel récursif, vous n'incluez pas l'élément en cours dans le résultat. Donc, vous supprimez tous les éléments E1. Changer l'appel récursif à:

(list* e2 (car l) (insert-elem e1 e2 (cdr l))) 

La version de travail est:

(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) 
+0

Merci beaucoup @Barmar .. Ça a beaucoup aidé! –

2

La variante LOOP, à titre de comparaison:

(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) 

La variante MAPCAN, pour le plaisir:

(defun insert-before (e1 e2 list) 
    (mapcan (lambda (e) 
      (if (equalp e e1) 
       (list e2 e1) 
       (list e))) 
      list))