10/22/2006

5.3細胞陣列

5.3Cell Array


細胞陣列與其他矩陣之情況略有不同,它在同一個陣列名稱下,儲存不同類型的資料陣列,諸如字串、文字、數值、複數、正整數陣列等,由於陣列之維數也容許不同,其應用的範圍更具彈性。有關細胞陣列之指令如下表:












指令型式 說明
A=cell(n) 產生一個n x n的空細胞陣列A
A=cell(m,n) 產生一個m x n的空細胞陣列A
celldisp(A) 顯示細胞陣列A之內容
cellplot(A) 繪出細胞陣列之佈置圖
[x,y,…]=deal(A,B,..) 進行串列配對,即x=A,y=B
[x,y,…]=deal(A) 進行串列配對,即x=A,y=A
iscell(A) 檢查A是否為細胞陣列,若是則傳回1,否則傳回0
A=num2cell(B) 將一數值矩陣B轉為細胞陣列A
cell2struct 將細胞陣列轉換為結構陣列
cellfun 應用細胞函數於一個細胞陣列



產生細胞陣列可利用指定陳述法,或用cell指令先安排細胞陣列之大小,然後再將資料移轉至各細胞存放。指定陳述法係將資料直接指定給特定細胞元素,一次一個。 MATLAB 將自動建立對應之細胞陣列。

將資料指定給某特定細胞有兩種方式:即細胞索引(cell indexing)與內容索引(content indexing)。細胞索引是先在等號左邊以下標說明細胞之位置,並且用一般標準的括符()括起來,如A(2,3)是;而等號之右邊則必須將所要設定的內容利用大括等{}括起來,表示該位置所設定的內容。例如為產生一個2 x 2的細胞陣列A:

>>A(1,1) = {[3 4 5; 1 5 7; 3 5 4]};
>>A(1,2) = {'馮丁樹'};
>>A(2,1) = {2:3:11};
>>A(2,2) = {-5+4j};
>>A
A =
[3x3 double] '馮丁樹'
[1x4 double] [-5.0000+ 4.0000i]

由這裡可以看出,產生一個細胞陣列可以如一般的矩陣指定方式一樣,將內容逐一填入。由於細胞陣列A之內容格式可能不一,故任何資料均可存放。此外,細胞中若為矩陣,則僅以矩陣之大小及數值內容表示。要注意的是等號右邊需用大括符,不能使用矩陣的中括符。而{}表示為空集合,是一種合法的型式。若要知道其實際內容,可以使用celldisp指令:

>>celldisp(A)
A{1,1} =
3 4 5
1 5 7
3 5 4

A{2,1} =
2 5 8 11
A{1,2} =馮丁樹
A{2,2} = -5.0000 + 4.0000i

此時所有內容均可以列出。若要以圖示表示此細胞陣列之相關位置,亦可使用cellplot指令,這是一個繪圖式指令。它會將各細胞之元素用圖表示出,但矩陣之內容仍不顯示。

>>cellplot(A)




內容索引則是在等號左邊以大括符定其位置,在等號右邊則置入實際之內容。其方式如下:

>>A{1,1} = [3 4 5; 1 5 7; 3 5 4];
A{1,2} = '馮丁樹';
A{2,1} = [2:3:11];
A{2,2} = -5+4j;
>>A
A =
[3x3 double] '馮丁樹'
[1x4 double] [-5.0000+ 4.0000i]

結果相同。換言之,在設定時,大括符僅能使用一次,不是在等號之左邊,就是在右邊。若所設定的資料位址超過原來的範圍,該細胞陣列會自動擴張,以配合需求。例如前述之A細胞陣列大小為2 x 2,若另外加一項內容,則會變為 3x3:

>>A(3,3)={'美麗的夏天'}
A =
[3x3 double] '馮丁樹' []
[1x4 double] [-5.0000+ 4.0000i] []
[] [] '美麗的夏天'

細胞陣列的語法中,利用大括符形成細胞內容之結構,與中括符作為一般矩陣的結構功能一樣;唯一相異之處是大括符允許其內又有大括符的巢狀結構。因此,細胞陣列中亦可包括另一個細胞陣列。在大括符中,係利用逗點或空格表示行向斷點,用分號作為細胞間之列向斷點。例如:

>>C = {[5 1 2], [9 7]; [1 7 3 4], [8 6 3]}
C =
[1x3 double] [1x2 double]
[1x4 double] [1x3 double]

利用cell指令則可預先設定一個細胞陣列之空集合,以事先保留此細胞陣列之架構。其中cell(n)可產生一個n x n之空細胞陣列:

>>D=cell(3, 4)
D =
[] [] [] []
[] [] [] []
[] [] [] []

若採用多項輸入時,可以直接利用陣列的內容陳述,元素中若為矩陣則必須以矩陣之方式表示;若為文字,則必須加上撇號,其前後則用大括符括起來:

>>D={'天龍八部' '金庸' 1988 [200 220 450]
'紅樓夢' '曹雪芹' 1890 [150 180 160]
'西遊記' '吳承恩' 1880 [120 140 100]};

>>D
D =
'天龍八部' '金庸' [1988] [1x3 double]
'紅樓夢' '曹雪芹' [1890] [1x3 double]
'西遊記' '吳承恩' [1880] [1x3 double]

若要單項輸入或修改,則在等號左邊採用一般括符之索引;右邊則採用大括符置放每個細胞之資料:

>>D(3,3)={1885}
D =
'天龍八部' '金庸' [1988] [1x3 double]
'紅樓夢' '曹雪芹' [1890] [1x3 double]
'西遊記' '吳承恩' [1885] [1x3 double]

實際上其指定方式亦可依細胞陣列元素之總排序之行列順序(亦即依第一行、第二行、…等之順序)。就上述第(3,3)之位置而言,其總排序順位應為9,故:

>>D(9)={1880}
D =
'天龍八部' '金庸' [1988] [1x3 double]
'紅樓夢' '曹雪芹' [1890] [1x3 double]
'西遊記' '吳承恩' [1880] [1x3 double]

又可將西遊記的年代更正為1880了。若要更改某細胞元素內之矩陣中之特定元素,則必須先使用大括符{}先指定細胞之位址,再用標準括符()定矩陣之位置。例如要更改D(3,4)中的第二項140為240時:

>>D{3,4}(1,2)=240
D{3,4}
ans =
120 240 100

顯示該項已經改正。

呼叫的程序亦相同,例如位置D(2,2):

>>D(2,2)
ans =
'曹雪芹'

>>D(1:3)
ans =
'天龍八部' '紅樓夢' '西遊記'

>>D(7:9)
ans =
[1988] [1890] [1880]

注意使用標準括號僅取其位址,而非其內容,要求第9項之內容必須使用大括符:

>>D{9}
ans = 1880

使用大括符可以將其內容組成新的矩陣,以供後來之應用:

>>P=[D{10};D{11};D{12}]
P =
200 220 450
150 180 160
120 240 100

利用細胞索引可以取出次陣列,設定給另外變數:

>>B=D(:,1:3)
B =
'天龍八部' '金庸' [1988]
'紅樓夢' '曹雪芹' [1890]
'西遊記' '吳承恩' [1880]

若僅為單細胞元素之內容,則使用一般括號或大括號索引均可,但若要取其中之之一項或部份時,則必須先使用大括符定位,然後再用一般型式索取矩陣中之個別內容。

若要取得細胞陣列中某特定項之內容,並置放對應之新變數時,可使用deal指令,但兩邊之項目必須相對應:

>>[book, author]=deal(D(:,1),D(:,2))
book =
'天龍八部'
'紅樓夢'
'西遊記'

author =
'金庸'
'曹雪芹'
'吳承恩'


deal這個指令等於進行配對的意思,將等號右邊之對應的資料配給左邊的變數,有如等號,只是其功能在於可同時處理許多變數或一系列變數,故特別適用於細胞陣列或下節要談到的結構資料。若右邊的資料僅有一項,則會以同樣的資料配給左邊的所有參數。這些參數可能是獨立的參數,也可能是另一陣列。例如:


>> sys = {rand(3) ones(3,1) eye(3) zeros(3,1)};
>> sys

sys =

[3x3 double] [3x1 double] [3x3 double] [3x1 double]

>> [a,b,c,d] = deal(sys{:});
>> a

a =

0.9501 0.4860 0.4565
0.2311 0.8913 0.0185
0.6068 0.7621 0.8214

>> b

b =

1
1
1

>> c

c =

1 0 0
0 1 0
0 0 1

>> d

d =

0
0
0



在細胞陣列中,若要刪除某一細胞,只要送給該細胞一個空集合即可,即D(…)=[]。這種細胞陣列亦可利用reshape函數進行大小重排,但整排後之矩陣大小需為原矩陣可除盡之數。

實際上細胞陣列有什麼好處?基於其容許不同大小及型式的內容之特性,有些應用依需要而定。它可以取代一些以逗點分開的變數名單,其中包括函數輸出入名單、作業過程之展示及陣列之建構等。由於MATLAB處理細胞陣列有如分離的變數。如:

>>C={[1 2 1], [1 0 1]}
C =
[1x3 double] [1x3 double]

可以使用細胞陣列中之元素作為其他函數之輸入參數,例如將兩多項式之係數相乘:

>>d=conv(C{1},C{2})
d =
1 2 2 2 1