Lisp語言:二維數組和多維數組

很多情況下只有一維數組是不夠用的,有時我們需要使用二維數組甚至是多維數組。

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 )  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章