Comment concaténer deux listes?

15

Désolé, mais elisp n'est pas mon meilleur. J'ai besoin de combiner deux listes de chaînes de cette façon:

("a" "b" "c") + ("d" "e" "f") -> ("a" "b" "c" "d" "e" "f")

Eh bien, la commande n'est pas importante, j'ai donc écrit ce code:

(while lista
  (add-to-list 'listb (car lista)) 
  (setq lista (cdr lista)))

Cela fonctionne, mais je me demande s'il y a une fonction qui fait déjà cela.

Un indice? Merci d'avance.

Daniele
la source
4
Voir les listes de construction de nœuds du manuel Elisp.
Drew
2
appendest la bonne réponse ici, mais une autre façon (destructrice) de le faire serait (setcdr (last a) b).
Sean Allred
1
Travailler sur des listes? dash.el ! (-concat '(1) '(2 3) '(4)) ;; => '(1 2 3 4)
Ehvince
Ne jamais utiliser add-to-listdans le code Lisp (cela est dit dans la docstring). Utilisez plutôt push.
Radon Rosborough

Réponses:

25

Vous pouvez également simplement utiliser append.

(append '("a" "b" "c") '("d" "e" "f"))
John Kitchin
la source
2
Et,(nconc '("a" "b" "c") '("d" "e" "f"))
lawlist
1
Oh, oui, en effet appendsemble mieux ici.
JeanPierre
nconc fonctionne mais, si vous stockez des listes dans des variables, elles seront modifiées par nconc. Par exemple (let ((a '(1 2 3)) (b' (3 4 5))) (nconc ab) a) modifiera la variable a.
John Kitchin
1
FYI cl-concatenateutilise appendlorsque TYPE est list, donc les deux réponses produisent le même résultat.
phils
Oui, ça fait sûrement le boulot. Un grand merci à tous pour votre aide.
Daniele
3

concatenate est un alias pour 'cl-concatenate' dans 'cl.el'.

(concaténer la SÉQUENCE DE TYPE ...)

Concatène, dans une séquence de type TYPE, l'argument SEQUENCEs.

Donc pour votre exemple

(concatenate 'list '("a" "b" "c") '("d" "e" "f"))

Puisqu'il est défini dans clvous devrez peut-être d' (require 'cl)abord, sinon vous pouvez utiliser cl-concatenatece qui semble être chargé par défaut.

De plus, comme souligné par @phils, il cl-concatenatesuffit d'appeler appendlorsque TYPE est 'list, voici la source de cl-extra.el:

(defun cl-concatenate (type &rest sequences)
  "Concatenate, into a sequence of type TYPE, the argument SEQUENCEs.
\n(fn TYPE SEQUENCE...)"
  (pcase type
    (`vector (apply #'vconcat sequences))
    (`string (apply #'concat sequences))
    (`list (apply #'append (append sequences '(nil))))
    (_ (error "Not a sequence type name: %S" type))))

Donc, si vous n'utilisez que des listes, il est plus simple d'utiliser directement append, comme l'a souligné @John Kitchin.

Enfin, @lawlist a mentionné nconc:

nconc est une fonction intégrée dans le «code source C».

(LISTES nconc & rest)

Concatène n'importe quel nombre de listes en les modifiant. Seul le dernier argument n'est pas modifié et n'a pas besoin d'être une liste.

Qu'est-ce que cela signifie:

(nconc '("a" "b" "c") '("d" "e" "f"))
=> ("a" "b" "c" "d" "e" "f")

(setq l1 '("a" "b" "c")
      l2 '("d" "e" "f"))
(nconc l1 l2)
=> ("a" "b" "c" "d" "e" "f")
l1
=> ("a" "b" "c" "d" "e" "f")
l2
=> ("d" "e" "f")
Jean Pierre
la source
Merci, mais il semble qu'il renvoie une erreur si les 2e et 3e arguments sont des variables et non des listes explicites.
Daniele
1
(setq l1 '("a" "b" "c") l2 '("d" "e" "f")) (concatenate 'list l1 l2)fonctionne bien.
JeanPierre
@Daniele Je soupçonne que vous essayez de citer les variables, ce qui signifie qu'elles ne sont pas évaluées par rapport à leurs valeurs de liste. (c'est-à-dire que vous voulez varnameplutôt que 'varname).
phils
Pour être complet, je pourrais aussi bien mentionner la manière non-CL de concaténer tout type de séquence dans Emacs> = 25: seq-concatenate(après (require 'seq)), bien que cela à son tour se termine cl-concatenate.
Basil