2010-12-08 6 views
5

Deux questions:En Lisp commun, comment puis-je insérer un élément dans une liste sur place?

1.I veulent une fonction pour insérer un élément dans une liste en place (dans toutes les positions, mais le début de la liste, voir la question 2 pour la raison) tel que:

CL> (defun insert-in-place (the-list after-position new-element) ....) => ... 
CL> (setf testy-list (list 'a 'b 'c 'd)) => ... 
CL> testy-list => ('A 'B 'C 'D) 
CL> (insert-in-place testy-list 1 'BOOOO) => ... 
CL> testy-list => ('A 'B 'BOOOO 'C 'D) 

2. Je pense que l'insertion d'un élément dans le début de la liste in-place est impossible à travers une fonction parce que les arguments sont passés par valeur, donc puisque la première cellule de la liste est passée, elle est passée en valeur et c'est une copie et ainsi changer sa voiture change seulement une voiture de copie, pas l'original, bien que les cellules contre suivantes soient partagées et le changement dans la place soit possible. Ai-je raison?

Répondre

8

1) voici:

(defun insert-after (lst index newelt) 
    (push newelt (cdr (nthcdr index lst))) 
    lst) 
(insert-after '(a c d) 0 'b) => (A B C D) 

2) modification destructive des cellules cons:

(setf testy-list '(a bar)) 
(defun modify (list) 
    (setf (first list) 'foo)) 
(modify testy-list) 
testy-list => (FOO BAR) 

Ceci définit la voiture de la première cellule de contre à « foo.

+0

Merci. À propos de la question 2: Lorsque vous appelez (modifiez la liste de tests), que faut-il modifier exactement? La 1ère contre cellule de test-liste en valeur ou sa référence? Je veux dire que vous avez répondu que je ne suis pas correct mais je ne peux pas trouver la faille dans mon argument sur la question 2 ... – Paralife

+0

Aussi j'ai fini par le faire moi-même: (rplacd (nthcdr position lst) (contre elem (nthcdr (+ 1 position) lst)))) mais le vôtre est meilleur. En fait je voulais setf le nthcdr, mais en clif que j'utilise, nthcdr n'est pas paramétrable. Je me demande si cela vaut la peine de le rendre paramétrable. Voir mon autre question: http://stackoverflow.com/questions/4387967/does-a-setfable-nthcdr-implementation-exist – Paralife

+0

A propos de la question 2: lorsque vous appelez (modifiez testy-list), vous passez une cellule par contre ("par référence"). – koddo

0

Je l'ai fait pour un de mes projets, gère l'index 0 et si l'index est supérieur à la longueur de la liste, le nouvel item est ajouté à la fin de la liste. Sachez qu'il crée une nouvelle liste de sorte qu'elle ne s'applique pas à votre cas. Je l'inclue en espérant que cela serait utile pour quelqu'un.

(defun list-insert-at (lst index new-value) 
    (let ((retval nil)) 
    (loop for i from 0 to (- (length lst) 1) do 
     (when (= i index) 
     (push new-value retval)) 
     (push (nth i lst) retval)) 
    (when (>= index (length lst)) 
     (push new-value retval)) 
    (nreverse retval))) 

CL-USER> test 
(1 2 3 4 5) 
CL-USER> (list-insert-at test 5 'a) 
(1 2 3 4 5 A) 
CL-USER> (list-insert-at test 0 'a) 
(A 1 2 3 4 5) 
Questions connexes