Lisp:多维数组元素运算

发布于 2024-10-01 11:44:48 字数 989 浏览 0 评论 0原文

Common Lisp 中将元素运算应用于多维数组的“正确”构造是什么?

以下示例应该有助于说明我正在尝试执行的操作:

A) 假设我想将数组的每个元素加一:

0 1 2    1 2 3
3 4 5 -> 4 5 6
6 7 8    7 8 9

B) 假设我想添加 2 个数组:

1 2   -1 -1    0 1
3 4 + -2 -2 -> 1 2
5 6   -3 -3    2 3

C) 假设我想按元素查找多个数组中最大的元素:

max( 0 1 , 4 -1 , 0 0 ) -> 4 1
     2 3   0  0   8 1      8 3

基本上我想我正在寻找某种“arraymap”函数,它可以像这样使用:(arraymap f A1 A2 ... An),其中 f 接受 n 个参数作为输入,并且Ai 是相同大小的数组。

在上面的例子中,它的使用方式如下:

A)

(setq M #2A((0 1 2) (3 4 5) (6 7 8)))
(arraymap #'incf M)

二)

(setq M #2A((1 2) (3 4) (5 6)))
(setq N #2A((-1 -1) (-2 -2) (-3 -3)))
(arraymap #'+ M N)

三)

(setq M #2A((0 1) (2 3)))
(setq N #2A((4 -1) (0 0)))
(setq O #2A((0 0) (8 1)))
(arraymap #'max M N O)

我尝试了一些使用映射和循环的构造,但它似乎不起作用,因为多维数组不是序列类型。

What is the "correct" construct in Common Lisp to apply elementwise operations to multidimensional arrays?

The following examples should help illustrate what I'm trying to do:

A) Suppose I want to increase every element of an array by one:

0 1 2    1 2 3
3 4 5 -> 4 5 6
6 7 8    7 8 9

B) Suppose I want to add 2 arrays:

1 2   -1 -1    0 1
3 4 + -2 -2 -> 1 2
5 6   -3 -3    2 3

C) Suppose I want to find the largest elements of several arrays, elementwise:

max( 0 1 , 4 -1 , 0 0 ) -> 4 1
     2 3   0  0   8 1      8 3

Basically I think I'm looking for some sort of "arraymap" function which would be used in like so: (arraymap f A1 A2 ... An), where f takes n arguments as input, and the Ai are arrays of the same size.

In the above examples it would be used like so:

A)

(setq M #2A((0 1 2) (3 4 5) (6 7 8)))
(arraymap #'incf M)

B)

(setq M #2A((1 2) (3 4) (5 6)))
(setq N #2A((-1 -1) (-2 -2) (-3 -3)))
(arraymap #'+ M N)

C)

(setq M #2A((0 1) (2 3)))
(setq N #2A((4 -1) (0 0)))
(setq O #2A((0 0) (8 1)))
(arraymap #'max M N O)

I have tried some constructs with map and loop, but it seems to not work since multidimensional arrays are not a sequence type.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

南笙 2024-10-08 11:44:48

有四种方法可以做到这一点:

  • 根据数组维度编写 ARRAY-MAP 函数并对其进行迭代。

  • 使用ROW-MAJOR-AREF,它可以像这样查看数组向量。

  • 使用移位的一维数组进行运算。

使用移位数组的示例:

(defun array-map (function &rest arrays)
  "maps the function over the arrays.
   Assumes that all arrays are of the same dimensions.
   Returns a new result array of the same dimension."
  (flet ((make-displaced-array (array)
           (make-array (reduce #'* (array-dimensions array))
                       :displaced-to array)))
    (let* ((displaced-arrays (mapcar #'make-displaced-array arrays))
           (result-array (make-array (array-dimensions (first arrays))))
           (displaced-result-array (make-displaced-array result-array)))
      (declare (dynamic-extent displaced-arrays displaced-result-array))
      (apply #'map-into displaced-result-array function displaced-arrays)
      result-array)))

使用它:

CL-USER 3 > (array-map #'1+ #2A((0 1 2) (3 4 5) (6 7 8)))

#2A((1 2 3) (4 5 6) (7 8 9))

CL-USER 4 > (array-map #'+ #2A((1 2) (3 4) (5 6)) #2A((-1 -1) (-2 -2) (-3 -3)) )

#2A((0 1) (1 2) (2 3))
  • 使用内部的、特定于实现的操作来进行高效的数组操作。

There are four ways to do that:

  • Write an ARRAY-MAP function based on the array dimensions and iterate over those.

  • Use ROW-MAJOR-AREF, which views the array like a vector.

  • Use displaced one-dimensional arrays for the operations.

Example for a use of displaced arrays:

(defun array-map (function &rest arrays)
  "maps the function over the arrays.
   Assumes that all arrays are of the same dimensions.
   Returns a new result array of the same dimension."
  (flet ((make-displaced-array (array)
           (make-array (reduce #'* (array-dimensions array))
                       :displaced-to array)))
    (let* ((displaced-arrays (mapcar #'make-displaced-array arrays))
           (result-array (make-array (array-dimensions (first arrays))))
           (displaced-result-array (make-displaced-array result-array)))
      (declare (dynamic-extent displaced-arrays displaced-result-array))
      (apply #'map-into displaced-result-array function displaced-arrays)
      result-array)))

Using it:

CL-USER 3 > (array-map #'1+ #2A((0 1 2) (3 4 5) (6 7 8)))

#2A((1 2 3) (4 5 6) (7 8 9))

CL-USER 4 > (array-map #'+ #2A((1 2) (3 4) (5 6)) #2A((-1 -1) (-2 -2) (-3 -3)) )

#2A((0 1) (1 2) (2 3))
  • Use internal, implementation specific, operations for efficient array operations.
终止放荡 2024-10-08 11:44:48

对于来这里寻找此问题最新答案的任何人:https://github.com /bendudson/array-operations 定义了 aops:each (和 aops:each*),它完全符合 OP 的要求。

For anyone coming here looking for an up-to-date answer to this question: https://github.com/bendudson/array-operations defines aops:each (and aops:each*) that does exactly what the OP asks for.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文