Как неразрушающим образом поменять местами две строки в двумерном массиве в Common Lisp

Я пытаюсь поменять местами две строки в двумерном массиве в Common Lisp. Я нашел способ сделать это с помощью aref. Это деструктивный способ сделать это, и я хотел бы, чтобы он был более функциональным. У кого-нибудь есть идея получше?

(defun swap-rows (matrix r1 r2)
  "Returns a modified matrix with two swapped rows"
  (loop for i upto (1- (array-dimension matrix 1))
    do (rotatef (aref copy r1 i) (aref copy r2 i))))

Я пытался сделать копию исходного массива, но он все еще меняет исходный массив. Это моя вторая попытка:

(defun swap-rows (matrix r1 r2)
  "Returns a modified matrix with two swapped rows"
  (let ((copy matrix))
    (loop for i upto (1- (array-dimension matrix 1))
      do (rotatef (aref copy r1 i) (aref copy r2 i))
      finally (return copy))))

Есть и другие вещи, на которые я смотрел, но некоторые способы копирования массива кажутся несколько слишком сложный. Заранее благодарю за любой совет.

P.S. Я предпочитаю не использовать сторонние библиотеки (очень жаль человека, который рекомендовал Александрию).

Структурированный массив Numpy
Структурированный массив Numpy
Однако в реальных проектах я чаще всего имею дело со списками, состоящими из нескольких типов данных. Как мы можем использовать массивы numpy, чтобы...
T - 1Bits: Генерация последовательного массива
T - 1Bits: Генерация последовательного массива
По мере того, как мы пишем все больше кода, мы привыкаем к определенным способам действий. То тут, то там мы находим код, который заставляет нас...
Что такое деструктуризация массива в JavaScript?
Что такое деструктуризация массива в JavaScript?
Деструктуризация позволяет распаковывать значения из массивов и добавлять их в отдельные переменные.
0
0
139
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ниже вы не копируете, а просто привязываете переменную (copy) к существующему значению (которое привязано к matrix):

(let ((copy matrix))
  ...)

Как видно из другого ответа, вы можете использовать библиотеку Александрия для копирования массива без особых сложностей; Например:

(alexandria:copy-array #2A((1 0 0)
                           (0 1 0)
                           (0 0 1)))

В вашем случае, если вы импортируете символ, достаточно написать:

(let ((copy (copy-array matrix)))
  ...)

Если вы меняете местами только строки без изменения их содержимого, возможно, вы можете определить матрицы как последовательности векторов. Вы бы разделили одни и те же строки, но в другом порядке (и если вам нужно изменить значения, вы можете скопировать векторы).

Ответ принят как подходящий

Копировать массив в Common Lisp не очень просто, и я думаю, это связано с тем, что массивы в этом языке представляют собой структуры данных, особенно подходящие для программирования с побочными эффектами, а не для программирования без побочных эффектов (или функционального). Как указал @coredump, если вы предпочитаете использовать программирование без побочных эффектов, вам, вероятно, следует использовать другие структуры данных, такие как список списков или последовательности векторов.

Если вы хотите придерживаться массивов, вот альтернативный способ сделать вашу копию (не очень простой и эффективный!):

(defun swap-rows (matrix r1 r2)
  "returns a copy of matrix with rows r1  ≤ r2 swapped"
  (let* ((rows (array-dimension matrix 0))
         (cols (array-dimension matrix 1)))
    (flet ((get-rows (from-r to-r)
             "get block of matrix from row from-r to row to-r excluded"
             (loop for i from from-r below to-r
                   collect (loop for j from 0 below cols
                                 collect (aref matrix i j)))))
      (make-array
       (list rows cols)
       :initial-contents
       (append (get-rows 0 r1)
               (get-rows r2 (1+ r2))
               (get-rows (1+ r1) r2)
               (get-rows r1 (1+ r1))
               (get-rows (1+ r2) rows))))))

На практике это преобразует исходный массив в блоки списков и перестраивает новый массив, начиная с этих списков.

Другие вопросы по теме