Come concatenare due elenchi?


15

Siamo spiacenti, ma elisp non è il massimo. Ho bisogno di combinare due elenchi di stringhe in questo modo:

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

Bene, l'ordine non è importante, quindi ho scritto questo codice:

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

Funziona, ma mi chiedo se c'è già una funzione che lo fa.

Qualche idea? Grazie in anticipo.


4
Vedi il nodo Elenchi di costruzione del manuale Elisp.
— Disegnò

2
appendè la risposta corretta qui, ma un altro modo (distruttivo) per farlo sarebbe (setcdr (last a) b).
— Sean Allred,

1
Stai lavorando su liste? dash.el ! (-concat '(1) '(2 3) '(4)) ;; => '(1 2 3 4)
— Ehvince,

Non usare mai add-to-listnel codice Lisp (dice questo nel docstring). Invece, usa push.
— Radon Rosborough,

Risposte:


25

Puoi anche semplicemente usare append.

(append '("a" "b" "c") '("d" "e" "f"))

2
E,(nconc '("a" "b" "c") '("d" "e" "f"))
— elenco delle leggi

1
Oh, sì, appendsembra davvero meglio qui.
— JeanPierre,

nconc funziona ma, se si memorizzano elenchi in variabili, verranno modificati da nconc. Ad esempio (let ((a '(1 2 3)) (b' (3 4 5))) (nconc ab) a) modificherà la variabile a.
— John Kitchin,

1
FYI cl-concatenateutilizza appendquando TYPE è list, quindi entrambe le risposte producono lo stesso risultato.
— phils

Sì, sicuramente fa il lavoro. Mille grazie a tutti per il vostro aiuto.
— Daniele,

3

concatenate è un alias per "cl-concatenate" in "cl.el".

(concatena SEQUENZA DI TIPO ...)

Concatenare, in una sequenza di tipo TYPE, l'argomento SEQUENCEs.

Quindi per il tuo esempio

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

Poiché è definito in cl, potrebbe essere necessario (require 'cl)innanzitutto, altrimenti è possibile utilizzare cl-concatenatequale sembra essere caricato per impostazione predefinita.

Inoltre, come sottolineato da @phils cl-concatenatechiama solo appendquando TYPE è 'list, ecco la fonte da 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))))

Quindi, se stai usando solo le liste, è più semplice da usare direttamente append, come sottolineato da @ John Kitchin.

Infine, @lawlist ha menzionato nconc:

nconc è una funzione integrata in "codice sorgente C".

(nconc & rest LISTE)

Concatena un numero qualsiasi di elenchi modificandoli. Solo l'ultimo argomento non viene modificato e non è necessario che sia un elenco.

Cosa significa:

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

Grazie, ma sembra che restituisca un errore se il secondo e il terzo argomento sono variabili e non elenchi espliciti.
— Daniele,

1
(setq l1 '("a" "b" "c") l2 '("d" "e" "f")) (concatenate 'list l1 l2)funziona bene
— JeanPierre,

@Daniele Sospetto che stavi cercando di citare le variabili, il che significa che non vengono valutate in base ai loro valori di elenco. (cioè vuoi varnamepiuttosto che 'varname).
— phils

Per completezza, potrei anche menzionare il modo non-CL di concatenare qualsiasi tipo di sequenza in Emacs> = 25: seq-concatenate(dopo (require 'seq)), sebbene questo a sua volta si concluda cl-concatenate.
— Basil
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.