【问题标题】:passing function output as another function argument for matrix transpose in lisp将函数输出作为 lisp 中矩阵转置的另一个函数参数传递
【发布时间】:2012-10-23 07:31:37
【问题描述】:

我正在用 lisp 编写矩阵转置函数。从以下代码可以看出我的做法:

(defun matrix-T (matrix)
  (cond ((null matrix) matrix)
        (t (list
            (do ((i 0 (+ i 1)))
                ((> i (length matrix)))
              (format t "(mapcar #'(lambda (x)(nth ~A x)) matrix)  %" i))))))

如您所见,我试图让 do 循环的输出作为 列表函数的参数。但是,我只得到从 matrix-T 返回的 do 循环输出。无论如何我可以纠正这个问题吗?

【问题讨论】:

  • 您的 DO 循环在返回值子表单中没有任何内容,因此它返回 NIL。它只是使用 FORMAT 函数将输出打印到*STANDARD-OUTPUT*。你想返回什么?
  • 我只是想让它返回它输出的文本
  • 但是输出和返回值不是一回事。您真的希望 matrix-T 返回字符串列表而不是新矩阵吗?
  • 概念是将输出作为参数输入到列表函数中,然后将返回一个新的矩阵。
  • 我将矩阵表示为列表中的列表。

标签: matrix lisp arguments output


【解决方案1】:

转置矩阵的非常简单直接的方法:

(defun transpose-matrix (matrix)
  (let ((result
         (make-array (reverse (array-dimensions matrix))
                     :element-type (array-element-type matrix))))
    (dotimes (i (array-dimension result 0) result)
      (dotimes (j (array-dimension result 1))
        (setf (aref result i j) (aref matrix j i))))))

(print
 (transpose-matrix
  #2A((1 2 3)
      (4 5 6))))
;; #2A((1 4) (2 5) (3 6)) 

【讨论】:

  • 非常感谢,我使用了列表,因为它们看起来更灵活,但速度一样快。
  • @Bracket:对于列表,您可以使用另一个答案中显示的应用地图车列表。然而,在 Common Lisp 中将矩阵表示为数组通常更自然、更高效,因为它具有真正的多维数组。
【解决方案2】:

您需要实际运行 MAPCAR 并将其结果收集到一个列表中,而不仅仅是打印或将其作为字符串返回。

(defun matrix-T (matrix)
  (cond ((null matrix) matrix)
        (t (do ((i 0 (1+ i))
                (result '())
                (cols (length (car matrix))))
               ((>= i cols) (nreverse result))
             (push (mapcar #'(lambda (x) (nth i x)) matrix) result)))))

【讨论】:

  • 非常感谢-请问,为什么do迭代器只返回完成的结果列表?
  • 它会返回您告诉它返回的任何内容。身体只是为了执行动作。如果您想要一个自动将数据收集到返回列表中的迭代宏,请使用 loop 及其 collect 操作。
  • 我的意思是它为什么不将步骤返回到已完成列表,而只是返回最终结果?
  • 因为这些步骤通常只是中间值,而不是你想要返回的东西。您可以控制想要返回的内容和不应该返回的内容。考虑该步骤是否是 if 语句,您想在其中选择是否返回该行。
  • 该控件是否以 (nreverse result) 表示?
【解决方案3】:

使用 mapcar* 进行转置的优雅方式

(defun transpose-matrix (matrix)
  (apply #'mapcar* #'list matrix))

(transpose-matrix '(("1" "a" "e") ("2" "b" "f") ("4" "c" "g") ("5" "d" "h")))

(("1" "2" "4" "5") ("a" "b" "c" "d") ("e" "f" "g" "h"))

【讨论】:

  • 什么是mapcar*,它与mapcar 有何不同?除此之外,这确实是一种使用列表的简单方法。
  • mapcar* 是 emacslisp 中 cl-mapcar 的别名 cl-mapcar 是“cl-lib.el”中编译的 Lisp 函数。 (cl-mapcar FUNCTION SEQ...) 将 FUNCTION 应用于 SEQ 的每个元素,并列出结果。如果有多个 SEQ,则使用那么多参数调用 FUNCTION,并且一旦最短列表用完,映射就会停止。只有一个 SEQ,这就像“地图车”。有几个,就像 Common Lisp 的“mapcar”函数扩展到任意序列类型。
猜你喜欢
  • 1970-01-01
  • 2022-12-09
  • 2013-09-10
  • 2021-11-29
  • 2017-08-07
  • 2019-05-20
  • 2015-05-29
  • 1970-01-01
  • 2022-11-12
相关资源
最近更新 更多