Bagaimana cara menggabungkan dua daftar?

15

Maaf, tapi elisp bukan yang terbaik. Saya perlu menggabungkan dua daftar string dengan cara ini:

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

Nah, urutannya tidak penting, jadi saya menulis kode ini:

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

Berhasil, tapi saya bertanya-tanya apakah ada fungsi yang sudah melakukan ini.

Ada petunjuk? Terima kasih sebelumnya.

Daniele
sumber
4
Lihat simpul Daftar Bangunan manual Elisp.
Drew
2
appendadalah jawaban yang benar di sini, tetapi cara lain (destruktif) untuk melakukannya adalah (setcdr (last a) b).
Sean Allred
1
Sedang mengerjakan daftar? dash.el ! (-concat '(1) '(2 3) '(4)) ;; => '(1 2 3 4)
Ehvince
Jangan pernah gunakan add-to-listdalam kode Lisp (ia mengatakan ini di docstring). Sebaliknya, gunakan push.
Radon Rosborough

Jawaban:

25

Anda juga bisa menggunakan append.

(append '("a" "b" "c") '("d" "e" "f"))
John Kitchin
sumber
2
Dan,(nconc '("a" "b" "c") '("d" "e" "f"))
hukum
1
Oh, ya, memang appendsepertinya lebih baik di sini.
JeanPierre
nconc berfungsi tetapi, jika Anda menyimpan daftar dalam variabel, mereka akan dimodifikasi oleh nconc. Misalnya (let ((a '(1 2 3)) (b' (3 4 5))) (nconc ab) a) akan memodifikasi variabel a.
John Kitchin
1
FYI cl-concatenatemenggunakan appendketika TYPE adalah list, jadi kedua jawaban menghasilkan hasil yang sama.
phils
Ya, itu pasti berhasil. Banyak terima kasih kepada semua orang atas bantuan Anda.
Daniele
3

concatenate adalah alias untuk 'cl-concatenate' di 'cl.el'.

(SEQUENCE TYPE gabungan ...)

Concatenate, menjadi urutan tipe TYPE, argumen SEQUENCEs.

Jadi untuk contoh Anda

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

Karena itu didefinisikan di clAnda mungkin harus (require 'cl)terlebih dahulu, jika tidak Anda dapat menggunakan cl-concatenateyang tampaknya dimuat secara default.

Juga, seperti yang ditunjukkan oleh @phils cl-concatenatehanya menelepon appendsaat TYPE sedang'list , inilah sumber dari 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))))

Jadi jika Anda hanya menggunakan daftar, lebih mudah digunakan secara langsung append, seperti yang ditunjukkan oleh @John Kitchin.

Akhirnya, @lawlist menyebutkan nconc:

nconc adalah fungsi bawaan di 'kode sumber C'.

(nconc & sisanya LISTS)

Gabungkan sejumlah daftar dengan mengubahnya. Hanya argumen terakhir yang tidak diubah, dan tidak perlu daftar.

Apa artinya ini:

(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")
JeanPierre
sumber
Terima kasih, tetapi sepertinya ia mengembalikan kesalahan jika argumen 2 dan 3 adalah variabel dan bukan daftar eksplisit.
Daniele
1
(setq l1 '("a" "b" "c") l2 '("d" "e" "f")) (concatenate 'list l1 l2)berfungsi ok.
JeanPierre
@Aniele Saya curiga Anda mencoba untuk mengutip variabel, yang berarti mereka tidak dievaluasi dengan nilai daftar mereka. (Yaitu Anda inginkan varnamedaripada 'varname).
phils
Untuk kelengkapan, saya mungkin juga menyebutkan cara non-CL untuk menggabungkan semua jenis urutan dalam Emacs> = 25: seq-concatenate(setelah (require 'seq)), meskipun ini pada gilirannya hanya membungkus cl-concatenate.
Basil