Имя этой функции во встроенной библиотеке Emacs Lisp?

Следующая функция Emacs Lisp принимает список списков и возвращает список, в котором элементы внутренних списков были объединены в один большой список. Это довольно прямолинейно, и я убежден, что что-то подобное уже должно быть частью стандартной библиотеки функций.

(defun flatten (LIST)
  (if LIST
      (append (car LIST) (flatten (cdr LIST)))
    nil))

Я ищу функцию, которая возьмет один список списков в качестве аргумента, а затем добавит все внутренние списки.

(flatten '((a b) (c d)))

даст

(a b c d)

Кто-нибудь знает, была ли эта функция уже встроена, и если да, то под каким именем?

Спасибо!

Ответ 1

Вы либо ищете append:

(defun flatten (list-of-lists)
  (apply #'append list-of-lists))

Если (и только если) вы знаете, что у вас всегда будет список списков.

В противном случае:

(defun flatten (list)
  (mapcan (lambda (x) (if (listp x) x nil)) list))

Ответ 2

Я вступил в это только недавно, ища что-то другое; есть что-то, что не могло быть доказано данными испытаний, используемыми для проверки функции, в зависимости от того, должен ли исходный вопрос ссылаться на общие списки (то есть: список списка списка списка...) или просто для двухуровневых списков (как в примере).

Решение основанное на append, отлично работает только с двухуровневыми списками, и есть еще одна проблема с на основе mapcan.

В общем, общее решение должно быть рекурсивным как на автомобиле, так и на cdr, как в flatten defun ниже.

(setq l '((((1 2) 3) 4) (5 6 7)))

(defun flatten(x)
  (cond ((null x) nil)
    ((listp x) (append (flatten (car x)) (flatten (cdr x))))
    (t (list x))))

(defun flatten2(l)
  (if l (append (car l) (flatten2 (cdr l))) nil))

(defun flatten3(l)
  (mapcan (lambda(x) (if (listp x) x nil)) l))

(flatten l)
(1 2 3 4 5 6 7)

(apply #'append l)
(((1 2) 3) 4 5 6 7)

(flatten2 l)
(((1 2) 3) 4 5 6 7)

Дальнейшая проблема заключается в использовании mapcan в flatten3: поскольку mapcan скрывает nconc внутри, пользователь должен помнить, что он изменяет свой аргумент.

l
((((1 2) 3) 4) (5 6 7))

(flatten3 l)
(((1 2) 3) 4 5 6 7)

l
((((1 2) 3) 4 5 6 7) (5 6 7))

Ответ 3

Dash - это современная библиотека списков для Emacs и сглажена. Это второй наиболее загруженный пакет на Melpa после магита. Из readme:

-flatten (l): принимает вложенный список l и возвращает его содержимое в виде единого плоского списка.

(-flatten '((1))) ;; => '(1)
(-flatten '((1 (2 3) (((4 (5))))))) ;; => '(1 2 3 4 5)
(-flatten '(1 2 (3 . 4))) ;; => '(1 2 (3 . 4))

-flatten-n (num list): выравнивать уровни num вложенного списка.

(-flatten-n 1 '((1 2) ((3 4) ((5 6))))) ;; => '(1 2 (3 4) ((5 6)))
(-flatten-n 2 '((1 2) ((3 4) ((5 6))))) ;; => '(1 2 3 4 (5 6))
(-flatten-n 3 '((1 2) ((3 4) ((5 6))))) ;; => '(1 2 3 4 5 6)

Этот пакет был запущен 2012-09.

Ответ 4

Я понимаю, что исходный вопрос был "что такое встроенная функция". Похоже, что их нет. Другие решения фактически не сглаживают все списки, которые я тестировал. Эта функция работает. Я размещаю его здесь, потому что это было первое место, когда Google ударил, когда я сделал свой поиск.

(defun flatten (LIST)
  "flattens LIST"
  (cond
   ((atom LIST) (list LIST))
   ((null (cdr LIST)) (flatten (car LIST)))
   (t (append (flatten (car LIST)) (flatten (cdr LIST))))))

например.

(flatten (list "a" (list "b" "c" nil) (list (list "d" "e") "f")))
("a" "b" "c" nil "d" "e" "f")

Ответ 5

Посмотрите nconc