2017-06-23 4 views
2

Ich habe zwei Elemente und eine Liste. Ich muss das zweite Element vor dem ersten Element jedes Mal, wenn das erste Element erscheint, in der ersten Ebene der gegebenen Liste einfügen.Ein Element1 vor einem Element2 einfügen

rekursive Version:

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

Aber etwas ist falsch, es Plätze anstelle des Einsatzes E2 vor E1 ändern. Könnte mir jemand helfen?

+0

Die Linie, die betteln ins mit '((Gleiches E2' macht die entgegengesetzte Einfügung, es setzt'E1' vor' E2'. – Barmar

+0

Was @Barmar? Ich habe es nicht verstanden. –

Antwort

3

Es gibt zwei Probleme.

Zuerst sollten Sie nur E2 vor E1 einfügen. Aber die Linie:

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

Einsätze E1 vor E2 auch. Sie sollten das entfernen.

Das zweite Problem besteht darin, dass Sie bei dem rekursiven Aufruf das aktuelle Element nicht in das Ergebnis einschließen. Sie entfernen also alle E1 Elemente. Ändern Sie den rekursiven Aufruf an:

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

Die Arbeitsversion ist:

(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

Vielen Dank @Barmar .. Es hat sehr geholfen! –

2

Die LOOP Variante zum Vergleich:

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

Die MAPCAN Variante für Spaß:

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