Como concatenar duas listas?

13

Desculpe, mas elisp não é o meu melhor. Preciso combinar duas listas de strings dessa maneira:

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

Bem, a ordem não é importante, então eu escrevi este código:

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

Funciona, mas estou me perguntando se existe uma função que já faça isso.

Qualquer pista? Desde já, obrigado.

Daniele
fonte
4
Consulte o nó Listas de construção do manual Elisp.
Tirou
2
appendé a resposta correta aqui, mas outra maneira (destrutiva) de fazer isso seria (setcdr (last a) b).
Sean Allred
1
Trabalhando em listas? dash.el ! (-concat '(1) '(2 3) '(4)) ;; => '(1 2 3 4)
Ehvince
Nunca use add-to-listno código Lisp (diz isso na documentação). Em vez disso, use push.
Radon Rosborough

Respostas:

24

Você também pode usar anexar.

(append '("a" "b" "c") '("d" "e" "f"))
John Kitchin
fonte
2
E,(nconc '("a" "b" "c") '("d" "e" "f"))
lawlist
1
Ah, sim, de fato appendparece melhor aqui.
JeanPierre 7/17/17
O nconc funciona, mas, se você armazenar listas em variáveis, elas serão modificadas pelo nconc. Por exemplo, (let ((a '(1 2 3)) (b' (3 4 5))) (nconc ab) a) modifica a variável a.
John Kitchin
1
FYI cl-concatenateusa appendquando TYPE é list, então ambas as respostas estão produzindo o mesmo resultado.
Phill
Sim, certamente faz o trabalho. Muito obrigado a todos por sua ajuda.
Daniele
3

concatenate é um alias para 'cl-concatenate' em 'cl.el'.

(concatenar a SEQUÊNCIA DE TIPO ...)

Concatene, em uma sequência do tipo TYPE, o argumento SEQUENCEs.

Então, para o seu exemplo

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

Como está definido, clvocê pode precisar (require 'cl)primeiro, caso contrário, você pode usar o cl-concatenateque parece ser carregado por padrão.

Além disso, como apontado por @phils cl-concatenateapenas chama appendquando TYPE é 'list, aqui está a fonte 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))))

Portanto, se você estiver usando apenas listas, é mais fácil usar diretamente append, como apontado por @John Kitchin.

Por fim, o @lawlist mencionou nconc:

O nconc é uma função interna do 'código fonte C'.

(lista Nconc e Rest)

Concatene qualquer número de listas alterando-as. Somente o último argumento não é alterado e não precisa ser uma lista.

O que isto 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")
Jean Pierre
fonte
Obrigado, mas parece que ele retorna um erro se o segundo e o terceiro argumentos forem variáveis ​​e não listas explícitas.
Daniele
1
(setq l1 '("a" "b" "c") l2 '("d" "e" "f")) (concatenate 'list l1 l2)funciona ok.
JeanPierre
@ Daniele Eu suspeito que você estava tentando citar as variáveis, o que significa que elas não são avaliadas com seus valores de lista. (ou seja, você quer varnamemais do que 'varname).
Phll
Para ser completo, eu também poderia mencionar a maneira não-CL de concatenar qualquer tipo de sequência no Emacs> = 25: seq-concatenate(depois (require 'seq)), embora isso, por sua vez, apenas envolva cl-concatenate.
Basil