2015年6月24日

陣列 (array) vs 清單 (list)

陣列(array) 和清單(list) 看似十分相似,卻又有一點點不一樣,熟悉陣列與清單的表示法絕對可以大大的增進工作效率!

陣列 (/ ... /)
陣列是「單一種類」變數的集合體,由整數組成的陣列叫做整數陣列,由小數組成的陣列叫做小數陣列,由文字組成的陣列叫做文字陣列,陣列的表示使用小括號和斜線將元素包總起來,以逗號做區隔:

IntArray = (/ 2 , 4 , 7 , 10 /)
FltArray = (/ 8.3 , 5.4 , 1.1 /)
StrArray = (/ "This" , "is" , "a" , "string" , "array." /)

上面三個例子是一維陣列,若要多維陣列可以像這樣寫:

IntMatrix = (/ (/ 1,2,3 /) , (/ 4,5,6 /) , (/ 7,8,9 /) /)

就會是一個 3 by 3 的二維陣列。要取出陣列中的元素或子集合,使用小括號:

IntElmt = IntArray(0)
; 得到 2
FltSubArray = FltArray(1:2)
; 得到 (/ 5.4 , 1.1 /)
IntSubMatrix = IntMatrix( 0:1 , 1:2 )
; 得到一個 2 by 2 的矩陣

清單 [/ ... /]
清單也是一種集合體,但是和陣列不同的地方在於清單可以同時容納任意類型、各種維度大小的變數,使用中括弧搭配斜線來表示。舉例來說:

ListA = [/ 6.2 , (/"A","bc"/) , IntArray , IntMatrix /]

清單 ListA 當中含有四個變數,第一個變數是一個浮點數,第二個變數是一個含有兩個元素的文字陣列,第三個變數是先前設定的整數陣列,第四個變數是二維的矩陣。取出清單中的變數,使用中括號:

Var2 = ListA[1]
; 得到第二個變數,兩個元素的文字陣列

陣列的擷取
假設一個三維的全球溫度場,包含15層氣壓層,1度x1度的資料,
這樣變數的維度就是 T ( 15 , 180 , 360 )

如果要擷取最低層溫度,

T_sub1 = T ( 0 , : , :)

再次提醒,NCL中,第一筆資料的index是 0。而純的「:」則代表「全部」。
如果要擷取最低三層的溫度,

T_sub2 = T ( 0:2 , : , : )

「0:2」就代表著第 0 層至第 2層。
如果要擷取第5層開始一直到最高層的資料,

T_sub3 = T ( 4: , : , : )

冒號後面不寫東西的話,就是一直到最後,同樣的方式也適用於 T ( :4 , : , : )

如果要擷取 500百帕北半球的溫度場,有兩種做法:
第一種,先利用 printVarSummary(T) 等方法找出 500百帕是第幾層,
緯度座標是遞增還是遞減等等,然後

T_sub4 = T ( 6 , 90:179 , :)

第二種方法,利用 { } 直接給定座標值

T_sub5 = T ( {500} , {0:90} , : )

如果變數T有正確的座標資訊,第二種方法會是比較方便而不容易出錯的

接下來,這個功能雖然不常用到,但是知道一下會在需要的時候省很多力氣 -- 轉置矩陣
不限於數學上那種二維的矩陣轉置,NCL可以快速的將座標轉換順序。舉例來說上述這個溫度變數 T 的三個座標軸名稱分別為 pLvl , Lat , Lon,原本習慣的排列順序應為 T (pLvl , Lat , Lon),但是如果今天有特殊需求,譬如需要畫剖面圖,或著某個特殊的函數 input 有規定要特定的排列順序,則可以這樣做

T_tans1 = T ( pLvl|: , Lon|: , Lat|: )

這樣原本 15x180x360 的陣列就會變成 15x360x180 的陣列了。當然也可以同時做擷取的動作

T_trans2 = T ( pLvl|0:2 , Lon|: , Lat|0:89 )

不同資料庫的儲存格式會因為各個單位或國家的使用習慣,有著不同的座標軸。資料的緯度做標在一些資料庫中是 -90~90,有些則是 90~-90。有一個快速的轉換方式

T_revlat = T ( : , ::-1 , :)

利用「: : -1」就可以將那個維度的做標反轉。

一些延伸
如果要做一個由1,2,3,4,...,100的整數陣列,可以用

Var1 = ispan(1,100,1)

如果想要1,2,3,...,100的浮點數陣列,

Var2 = ispan(1,100,1) * 1.0

如果要將0到360度等分分成100個網格點,

Var3 = fspan(0,360,100)

如果要清除一個暫存空間裡的變數,

delete(Var1)

如果要一次刪除多個變數,記得要用"清單"而非"陣列"的方式表示,

delete( [/ Var1 , Var2 , Var3 /] )

Take Home Message
一些小東西很難分類歸納,我隨便寫寫,大家也就隨便看看就好

沒有留言:

張貼留言