我正在尝试将两行交换在二维数组中。我已经使用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))))))
实际上,此列表中的原始数组将原始数组转换为从这些列表开始的新数组。