Як об'єднати два списки?


15

Вибачте, але Elisp - це не найкраще. Мені потрібно поєднувати два списки рядків таким чином:

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

Ну а порядок не важливий, тому я написав цей код:

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

Це працює, але мені цікаво, чи є функція, яка вже робить це.

Якась підказка? Заздалегідь спасибі.


4
Дивіться списки побудови вузлів у посібнику Elisp.
Дрю

2
appendтут правильна відповідь, але інший (руйнівний) спосіб це був би (setcdr (last a) b).
Шон Аллред

1
Робота над списками? dash.el ! (-concat '(1) '(2 3) '(4)) ;; => '(1 2 3 4)
Переконайтеся

Ніколи не використовуйте add-to-listв коді Lisp (це написано в docstring). Натомість використовуйте push.
Радон Росборо

Відповіді:


25

Ви також можете просто використовувати додавання.

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

2
І,(nconc '("a" "b" "c") '("d" "e" "f"))
законник

1
О так, справді appendтут здається краще.
ЖанП'єр

nconc працює, але, якщо ви зберігаєте списки у змінних, вони будуть змінені nconc. Наприклад (нехай ((a '(1 2 3)) (b' (3 4 5))) (nconc ab) a) змінить змінну.
Джон Кітчін

1
FYI cl-concatenateвикористовує, appendколи TYPE є list, тому обидві відповіді дають однаковий результат.
філс

Так, це, безумовно, робить свою роботу. Велике спасибі всім за допомогу.
Даніеле

3

concatenate - псевдонім для 'cl-concatenate' у 'cl.el'.

(об'єднати послідовність ТИПУ ...)

Об'єднайте в послідовність типу TYPE аргумент SEQUENCE.

Тож для вашого прикладу

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

Оскільки це визначено у clвас, можливо, доведеться (require 'cl)спочатку, інакше ви можете використовувати те, cl-concatenateщо здається завантажене за замовчуванням.

Також, як зазначає @phils, cl-concatenateпросто дзвонить, appendколи TYPE є 'list, ось джерело з 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))))

Тож якщо ви використовуєте лише списки, це простіше безпосередньо використовувати append, як вказував @John Kitchin.

Нарешті, @lawlist згадав nconc:

nconc - це вбудована функція у "C вихідному коді".

(списки nconc та решта)

Об’єднайте будь-яку кількість списків, змінивши їх. Тільки останній аргумент не змінюється, і його список не повинен бути.

Що це означає:

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

Дякую, але схоже, що він повертає помилку, якщо другий та третій аргументи є змінними, а не явними списками.
Даніеле

1
(setq l1 '("a" "b" "c") l2 '("d" "e" "f")) (concatenate 'list l1 l2)працює добре.
ЖанП'єр

@Daniele Я підозрюю, що ви намагалися цитувати змінні, це означає, що вони не оцінюються до їх списку значень. (тобто varnameшвидше ви хочете 'varname).
філи

Для повноти я можу також згадати не-CL спосіб об'єднання будь-якого типу послідовностей в Emacs> = 25: seq-concatenate(після (require 'seq)), хоча це, в свою чергу, просто завершує роботу cl-concatenate.
Василь
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.