如何在共同的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。我宁愿不使用任何外部图书馆(对推荐亚历山大的人非常抱歉)。

在这里您没有进行副本,只将变量(copy)绑定到现有值(绑定到matrix):

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

在另一个答案中可以看到,您可以使用 alexandria库库复制数组而无需过多复杂。例如:

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

在您的情况下,如果导入符号,则足以写:

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

如果您仅交换行而没有修改其内容,则也许您可以将矩阵定义为向量序列。您将共享相同的行,但在不同的订单中(如果您需要更改值,则可以复制向量)。

在共同的LISP中复制数组并不是特别简单,我认为这是由于该语言中的数组是数据结构,特别适合副作用编程而不是侧面 - 无效的(或功能)编程。正如@coreump所指出的那样,如果您喜欢使用副作用免费编程,则可能应该使用其他数据结构,例如列表列表或向量的序列。

如果您想坚持数组,这是进行副本的另一种方法(不是很简单或高效!):

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

实际上,此列表中的原始数组将原始数组转换为从这些列表开始的新数组。

最新更新