Lisp语言:二维数组和多维数组

来源:互联网 发布:td200文本显示器编程 编辑:程序博客网 时间:2024/04/27 15:35

很多情况下只有一维数组是不够用的,有时我们需要使用二维数组甚至是多维数组。

Lisp中二维数组的使用和一维数组很接近,都是使用make-array函数来创建。

创建一维数组的样例如下:

[plain] view plaincopy
  1. (setf test-array-1 (make-array 10 :initial-element "xxx"))  
而创建二维数组的样例看起来非常相似:

[plain] view plaincopy
  1. (setf test-array-2 (make-array '(3 5) :initial-element "xxx"))  

比较两行语句可以发现,创建二维数组和创建一维数组不同的就是make-array后面跟着的参数,也就是维度的参数。

创建一维数组时“维度参数”是一个数字,指定数组的长度。

创建二维数组时“维度参数”是一个列表,像这样:'( 3  5)。因为我们到目前为止还没有详细讨论列表,所以不对这种形式做详细分析。我们先不管为什么,反正先记住定义二维数组时“维度参数”是一个单引号后面跟一对括号,括号中两个数字,分别是两个维度的长度。

所以上面的样例代码定义了一个3*5的二维数组。


和一维数组一样,访问二维数组的元素可以使用函数aref,不过参数多一个。下面是访问test-array-2 数组中的元素的样例:

[plain] view plaincopy
  1. (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)”:

[plain] view plaincopy
  1. (array-dimensions test-array-2)  
知道了一个二维数组所有维度的长度,结合loop循环就可以对一个二维数组进行遍历了,不过需要对arrar-dimensions函数的返回值进行处理,以分别得到第一维度和第二维度的长度。

其实现实中不用这么麻烦,Lisp提供了另一个函数获取二维数组,甚至是多维数组不同维度的长度,就是函数array-dimension,注意array-dimension后面是不带s的。

如,下面的代码可以获得数组test-array-2第一个维度的长度。

[plain] view plaincopy
  1. (array-dimension test-array-2 0)  
对应地,下面的代码可以获得数组test-array-2第二个维度的长度。

[plain] view plaincopy
  1. (array-dimension test-array-2 1)  

所以,下面的代码就可以对数组test-array-2进行遍历,输出所有元素的值:

[plain] view plaincopy
  1. (loop for i from 0 below (array-dimension test-array-2 0) do   
  2.                 (loop for j from 0 below (array-dimension test-array-2 1) do  
  3.                         (format *query-io* "element ~a ~a is ~a ~%"  
  4.                                 i  
  5.                                 j  
  6.                                 (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函数的方法,如:

[plain] view plaincopy
  1. (setf (aref test-array-2 1 3) "yyyyyyy")  
以上代码对test-array-2数组下标为(1,3)的元素进行赋值,值为“yyyyyyy”


以下为二维数组定义,修改,遍历的完整代码和执行结果截图:

[plain] view plaincopy
  1. (defun array-test-2 ()  
  2.         (setf test-array-2 (make-array '(3 5) :initial-element "xxx"))  
  3.    
  4.         (setf array-dim-2 (array-dimensions test-array-2))  
  5.         (format *query-io* "Dimension of array-test-2 is: ~a ~%" array-dim-2)  
  6.   
  7.         (setf (aref test-array-2 1 3) "yyyyyyy")  
  8.         (setf (aref test-array-2 2 3) "ttttttt")  
  9.   
  10.         (loop for i from 0 below (array-dimension test-array-2 0) do   
  11.                 (loop for j from 0 below (array-dimension test-array-2 1) do  
  12.                         (format *query-io* "element ~a ~a is ~a ~%"  
  13.                                 i  
  14.                                 j  
  15.                                 (aref test-array-2 i j)))))  



知道了二维数组的使用方法,三维数组甚至是多维数组就比较简单了,使用方法类似,就是维度参数不同。

如四维数组的定义如下:

[plain] view plaincopy
  1. (setf test-array-3 (make-array '(3 5 6 9) :initial-element "xxx"))  

获取test-array-3第4个维度的长度的代码如下:

[plain] view plaincopy
  1. (array-dimension test-array-3 3)  

获得test-array-3数组中下标为( 2 2 2 2)元素的代码如下:

[plain] view plaincopy
  1. (aref test-array-3 2 2 2 2 )  
0 0