【问题标题】:How to swap two rows in a twodimensional array in common lisp nondestructively如何在普通lisp中无损交换二维数组中的两行
【发布时间】:2019-02-23 19:20:15
【问题描述】:

我正在尝试在 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))))

我还看过其他一些东西,但复制数组的一些方法似乎有点overly complicated。提前感谢您的任何建议。

附:我不想使用任何外部库(非常抱歉推荐 Alexandria 的人)。

【问题讨论】:

    标签: arrays multidimensional-array functional-programming common-lisp


    【解决方案1】:

    在下面你不是在做复制,只是将一个变量 (copy) 绑定到一个现有值(绑定到 matrix 的那个):

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

    正如在另一个答案中看到的,您可以使用Alexandria 库来复制数组,而不需要太多复杂性;例如:

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

    在你的情况下,如果你导入符号,写就足够了:

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

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

    【讨论】:

      【解决方案2】:

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

      实际上,这会将原始数组转换为列表块,并从这些列表开始重建一个新数组。

      【讨论】:

        猜你喜欢
        • 2020-12-20
        • 2020-09-06
        • 2021-03-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-02-09
        • 2018-10-15
        • 1970-01-01
        相关资源
        最近更新 更多