Wie verkettet man zwei Listen?

13

Entschuldigung, aber elisp ist nicht mein Bestes. Ich muss zwei Listen von Zeichenfolgen auf diese Weise kombinieren:

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

Nun, die Reihenfolge ist nicht wichtig, also habe ich diesen Code geschrieben:

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

Es funktioniert, aber ich frage mich, ob es eine Funktion gibt, die dies bereits tut.

Irgendeine Ahnung? Danke im Voraus.

Daniele
quelle
4
Siehe Knoten Building Lists des Elisp-Handbuchs.
Drew
2
appendHier ist die richtige Antwort, aber ein anderer (destruktiver) Weg wäre es (setcdr (last a) b).
Sean Allred
1
Arbeiten an Listen? dash.el ! (-concat '(1) '(2 3) '(4)) ;; => '(1 2 3 4)
Ehvince
Niemals add-to-listin Lisp-Code verwenden (dies steht im Docstring). Verwenden Sie stattdessen push.
Radon Rosborough

Antworten:

23

Sie können auch einfach append verwenden.

(append '("a" "b" "c") '("d" "e" "f"))
John Kitchin
quelle
2
Und,(nconc '("a" "b" "c") '("d" "e" "f"))
Gesetzesliste
1
Oh ja, appendhier scheint es tatsächlich besser zu sein.
JeanPierre
nconc funktioniert, aber wenn Sie Listen in Variablen speichern, werden sie von nconc geändert. Beispiel: (let ((a '(1 2 3)) (b' (3 4 5))) (nconc ab) a) ändert die a-Variable.
John Kitchin
1
FYI cl-concatenateverwendet, appendwenn TYPE ist list, sodass beide Antworten das gleiche Ergebnis liefern .
Phils
Ja, es macht sicherlich den Job. Vielen Dank an alle für Ihre Hilfe.
Daniele
3

verketten ist ein Alias ​​für 'cl-verketten' in 'cl.el'.

(TYPE SEQUENCE verketten ...)

Verketten Sie das Argument SEQUENCEs in eine Sequenz vom Typ TYPE.

Also für dein Beispiel

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

Da es in definiert ist, müssen clSie möglicherweise (require 'cl)zuerst, ansonsten können Sie verwenden, cl-concatenatewas standardmäßig geladen zu sein scheint.

Wie von @phils hervorgehoben, cl-concatenateruft @phils nur auf, appendwenn TYPE ist 'list. Hier ist die Quelle von 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))))

Wenn Sie also nur Listen verwenden, ist die direkte Verwendung einfacher append, wie von @John Kitchin ausgeführt.

Schließlich erwähnte @lawlist nconc:

nconc ist eine integrierte Funktion in 'C-Quellcode'.

(Nconc & Rest Listen)

Verketten Sie beliebig viele Listen, indem Sie sie ändern. Nur das letzte Argument wird nicht geändert und muss keine Liste sein.

Was das bedeutet:

(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
quelle
Danke, aber es sieht so aus, als würde ein Fehler zurückgegeben, wenn das 2. und 3. Argument Variablen und keine expliziten Listen sind.
Daniele
1
(setq l1 '("a" "b" "c") l2 '("d" "e" "f")) (concatenate 'list l1 l2)funktioniert ok
JeanPierre
@ Daniele Ich vermute, Sie haben versucht, die Variablen in Anführungszeichen zu setzen , was bedeutet, dass sie nicht nach ihren Listenwerten ausgewertet werden. (dh du willst varnamelieber als 'varname).
Phils
Der Vollständigkeit halber möchte ich auch die nicht CL-konforme Verkettung einer Sequenz in Emacs> = 25: seq-concatenate(after (require 'seq)) erwähnen cl-concatenate.
Basil