很多情况下只有一维数组是不够用的,有时我们需要使用二维数组甚至是多维数组。
Lisp中二维数组的使用和一维数组很接近,都是使用make-array函数来创建。
创建一维数组的样例如下:
(setf test-array-1 (make-array 10 :initial-element "xxx"))而创建二维数组的样例看起来非常相似:
(setf test-array-2 (make-array '(3 5) :initial-element "xxx"))
比较两行语句可以发现,创建二维数组和创建一维数组不同的就是make-array后面跟着的参数,也就是维度的参数。
创建一维数组时“维度参数”是一个数字,指定数组的长度。
创建二维数组时“维度参数”是一个列表,像这样:'( 3 5)。因为我们到目前为止还没有详细讨论列表,所以不对这种形式做详细分析。我们先不管为什么,反正先记住定义二维数组时“维度参数”是一个单引号后面跟一对括号,括号中两个数字,分别是两个维度的长度。
所以上面的样例代码定义了一个3*5的二维数组。
和一维数组一样,访问二维数组的元素可以使用函数aref,不过参数多一个。下面是访问test-array-2 数组中的元素的样例:
(aref test-array-2 1 3)
以上代码获得test-array-2这个二维数组中第二行第四列的元素,或者说是取得test-array-2数组中下标为“1,3”的元素。
同样,需要注意Lisp中数组下标是以0开始计算的。
如果需要对Lisp中的二维数组进行遍历,依赖length函数是不行的了,在不知道维度的情况下单纯靠一个二维数组的长度是无法遍历它的。事实上如果在length函数中传入一个二维数组的话系统会报错的。
希望获取一个二维数组的维度可以使用array-dimensions函数,注意array-dimension后面有个s。
array-dimentions函数会返回一个列表,保存着目标数组不同维度的长度。
按以上样例对test-array-2的定义,下面的样例代码会返回“(3 5)”:
(array-dimensions test-array-2)知道了一个二维数组所有维度的长度,结合loop循环就可以对一个二维数组进行遍历了,不过需要对arrar-dimensions函数的返回值进行处理,以分别得到第一维度和第二维度的长度。
其实现实中不用这么麻烦,Lisp提供了另一个函数获取二维数组,甚至是多维数组不同维度的长度,就是函数array-dimension,注意array-dimension后面是不带s的。
如,下面的代码可以获得数组test-array-2第一个维度的长度。
(array-dimension test-array-2 0)对应地,下面的代码可以获得数组test-array-2第二个维度的长度。
(array-dimension test-array-2 1)
所以,下面的代码就可以对数组test-array-2进行遍历,输出所有元素的值:
(loop for i from 0 below (array-dimension test-array-2 0) do (loop for j from 0 below (array-dimension test-array-2 1) do (format *query-io* "element ~a ~a is ~a ~%" i j (aref test-array-2 i j))))注意以上代码使用loop循环时使用了below而不是to做为循环条件
loop for i from 0 to x 相当于是java中的 for (int i=0 ;i==x;i++)
而loop for i from 0 below x相当于是java中的 for (int i=0 ;i<x ;i++)
最后,如果希望对数组某个元素进行赋值操作,可以使用setf函数结合aref函数的方法,如:
(setf (aref test-array-2 1 3) "yyyyyyy")以上代码对test-array-2数组下标为(1,3)的元素进行赋值,值为“yyyyyyy”
以下为二维数组定义,修改,遍历的完整代码和执行结果截图:
(defun array-test-2 () (setf test-array-2 (make-array '(3 5) :initial-element "xxx")) (setf array-dim-2 (array-dimensions test-array-2)) (format *query-io* "Dimension of array-test-2 is: ~a ~%" array-dim-2) (setf (aref test-array-2 1 3) "yyyyyyy") (setf (aref test-array-2 2 3) "ttttttt") (loop for i from 0 below (array-dimension test-array-2 0) do (loop for j from 0 below (array-dimension test-array-2 1) do (format *query-io* "element ~a ~a is ~a ~%" i j (aref test-array-2 i j)))))
知道了二维数组的使用方法,三维数组甚至是多维数组就比较简单了,使用方法类似,就是维度参数不同。
如四维数组的定义如下:
(setf test-array-3 (make-array '(3 5 6 9) :initial-element "xxx"))
获取test-array-3第4个维度的长度的代码如下:
(array-dimension test-array-3 3)
获得test-array-3数组中下标为( 2 2 2 2)元素的代码如下:
(aref test-array-3 2 2 2 2 )