Общий Lisp: конвертировать между списками и массивами

Как мы можем элегантно преобразовывать между произвольно вложенными списками и массивами?

например.

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

становится

#2A((1 2 3) (4 5 6))

и наоборот

Ответы

Ответ 1

Список массивов 2d:

(defun list-to-2d-array (list)
  (make-array (list (length list)
                    (length (first list)))
              :initial-contents list))

2d для списка:

(defun 2d-array-to-list (array)
  (loop for i below (array-dimension array 0)
        collect (loop for j below (array-dimension array 1)
                      collect (aref array i j))))

Многомерная форма для списка на 2d проста.

(defun list-dimensions (list depth)
  (loop repeat depth
        collect (length list)
        do (setf list (car list))))

(defun list-to-array (list depth)
  (make-array (list-dimensions list depth)
              :initial-contents list))

Массив для списка сложнее.

Возможно, что-то вроде этого:

(defun array-to-list (array)
  (let* ((dimensions (array-dimensions array))
         (depth      (1- (length dimensions)))
         (indices    (make-list (1+ depth) :initial-element 0)))
    (labels ((recurse (n)
               (loop for j below (nth n dimensions)
                     do (setf (nth n indices) j)
                     collect (if (= n depth)
                                 (apply #'aref array indices)
                               (recurse (1+ n))))))
      (recurse 0))))

Ответ 2

Еще один массив 2d для списка решений:

(defun 2d-array-to-list (array)
  (map 'list #'identity array))

И список для 2d массива (но, возможно, не так эффективен, как решение последнего ответа):

(defun list-to-2d-array (list)
  (map 'array #'identity list))