Lisp:多维数组元素操作
Posted
技术标签:
【中文标题】Lisp:多维数组元素操作【英文标题】:Lisp: multidimensional array elementwise operations 【发布时间】:2011-05-06 04:32:40 【问题描述】: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 是相同大小的数组。
在上面的例子中,它会这样使用:
一)
(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)
我尝试了一些带有 map 和 loop 的构造,但它似乎不起作用,因为多维数组不是序列类型。
【问题讨论】:
【参考方案1】:有四种方法可以做到这一点:
根据数组维度编写一个 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))
使用内部的、特定于实现的操作来实现高效的数组操作。
【讨论】:
啊,太好了。您可能会说这就像使用 matlab 样式的“ind2sub”和“sub2ind”函数一样隐式。【参考方案2】:对于任何来这里寻找此问题最新答案的人:https://github.com/bendudson/array-operations 定义了完全符合 OP 要求的 aops:each
(和 aops:each*
)。
【讨论】:
以上是关于Lisp:多维数组元素操作的主要内容,如果未能解决你的问题,请参考以下文章