異質陣列 (Cell Arrays) 方煒 台大生機系
ver. 5 之後才支援的資料型態
異質陣列 (Cell Arrays) 可儲存各種不同型態的 MATLAB 資料 Cell Arrays => 「盒子陣列」!? 「異質」 => 「不同性質的資料型態」
建立異質陣列 - Cell Indexing Ex: cell01.M A(1,1) = {'This is the first cell.'}; A(1,2) = {[5+j*6 , 4+j*5]}; A(2,1) = {[1 2 3; 4 5 6; 7 8 9]}; A(2,2) = {{'Tim'; 'Chris'}}
Cell-Indexing (cont) 上例建立了一個二維異質陣列A:2*2內容如下: A(1,1): 'This is the first cell' 字串 A(1,2): [5+j*6 4+j*5] 1*2複數陣列 A(2,1): 1 2 3 4 5 6 7 8 9 3*3整數陣列 A(2,2): {'Tim', 'Chris'} 2*2異質陣列
建立異質陣列 - Content Indexing 做法:矩陣() → 異質陣列{} Ex:cell02.m A{1,1} = 'this is the first cell.'; A{1,2} = [5+j*6, 4+j*5]; A{2,1} = [1 2 3; 4 5 6; 7 8 9]; A{2,2} = {'Tim'; 'Chris'} 結果同上例
建立異質陣列 – 使用大括號 {} 第三種方法是直接用大括號一次把所有元素括起來 Ex: >> B = {'James Bond', [1 2;3 4;5 6]; pi, magic(5)} >> C = {rand(3), ones(2); zeros(5), randperm(4)} B = 'James Bond' [3x2 double] [ 3.1416] [5x5 double] C = [3x3 double] [2x2 double] [5x5 double] [1x4 double]
異質陣列的合併 對於異質陣列的合併,大致上跟陣列合併相同 Ex: (B,C如上頁) >> M = [B C] % 將異質陣列 B 及 C 左右並排 M = 'James Bond‘ [3x2 double] [3x3 double] [2x2 double] [ 3.1416] [5x5 double] [5x5 double] [1x4 double]
異質陣列的內容顯示 直接呼叫? => maybe not 若在 MATLAB 指令視窗內,直接呼叫異質陣列的名稱,MATLAB 並不直接顯示異質陣列各元素的值, 只能顯示各元素的資料型態及維度 Ex: >> A A = [1x23 char ] [1x2 double] [3x3 double] {2x1 cell }
Cellplot圖示型態 cellplot 指令可將異質陣列的內部資料型態,以圖形的方式顯示 Ex:cell03.m A{1,1} = 'this is the first cell.'; A{1,2} = [5+j*6, 4+j*5]; A{2,1} = [1 2 3; 4 5 6; 7 8 9]; A{2,2} = {'Tim'; 'Chris'}; cellplot(A) % 以圖形的方式顯示異質陣列 A 的內部資料型態
Result
另例:output of cellplot
celldisp顯示 Ex: >> celldisp(A) % 顯示異質陣列 A 各個構成元素的實際內容 A{1,1} = this is the first cell. A{2,1} = 1 2 3 4 5 6 7 8 9 A{1,2} = 5.0000 + 6.0000i 4.0000 + 5.0000i A{2,2}{1} = Tim A{2,2}{2} = Chris
Content Indexing顯示 先前提過建立異質陣列的方法 - Content Indexing,其實也可以用來直接將異質陣列 A 的各個構成元素內容一次全部顯示出來 用法: 要查看A的內容,在MATLAB下直接輸入: >> A{:} % 顯示異質陣列 A 的全部構成元素
Result ans = this is the first cell. 1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9 5.0000 + 6.0000i 4.0000 + 5.0000 ‘Tim’ ‘Chris’
異質陣列的內容取用 直接取用異質陣列的cell 取用異質陣列的元素的內部構成單位 一次同時取用或刪除多個元素 異質陣列可以取代以逗點分開的變數列
直接取用異質陣列的cell 以下例子先建立一個異質陣列 B,再取用其中第 1 橫列、第 2 直行的元素: >> B = {'James Bond', [1 2;3 4;5 6]; pi, magic(5)} B = 'James Bond' [3x2 double] [ 3.1416] [5x5 double]
直接取用異質陣列的cell (cont) >> F = B{1,2} Result: F = 1 2 3 4 5 6 1 2 3 4 5 6
取用異質陣列元素的內部構成單位 先用 Content Indexing 的方法,再直接加上一般矩陣的索引法 Ex: G = 5 >> G = B{1,2}(3,1) G = 5
同時取用或刪除多個元素 如上述異質陣列B >> H = B(2,:) %取用異質陣列 B 的第一橫列所有元素 H = [3.1416] [5x5 double] >> B(1,:) = [] %刪除異質陣列 B 的第一橫列所有元素 B =
取代以逗點分開的變數列 Ex: %先建立一個維度為 1×4 的異質陣列 >> F = {[2 3 5], [1 2 3], 'Timmy', 'Annie'}; >> F{1:2} ans = 2 3 5 1 2 3
取代以逗點分開的變數列 上例中, F{1:2} 會指向 「[2 3 5], [1 2 2]」 可將之用於函數的輸入變數列,例如: >> plot(F{1:2}, '-o') Result:
取代以逗點分開的變數列(cont) 同理,亦可將之用於輸出變數列: Ex: >> [F{1:2}] = max(rand(5)) [1x5 double] [1x5 double] %F為一1x2的異質陣列
其他相關指令 改變異質陣列的大小 事先預設(Pre-Allocate)空的異質陣列 測試某一變數是否為異質陣列 將一數值陣列轉換成異質陣列 將一結構陣列的所有欄位值轉換成異質陣列 將異質陣列轉換為結構陣列 將一結構陣列的某一欄位值轉換成異質陣列
改變異質陣列的大小 可使用「:」運算或「reshape」 Ex: B為2x2異質陣列 B = 'James Bond‘ [3x2 double] [ 3.1416] [5x5 double] Result: >> M = B(:) M = 'James Bond' [ 3.1416] [3x2 double] [5x5 double] >> N = reshape(B,1,4) N = 'James Bond' [3.1416] [3x2 double] [5x5 double]
預設空的異質陣列 利用 cell 指令 Ex: >> E = cell(4, 3) % 事先預設一個 4×3 空的異質陣列 Result: E = [] [] []
測試某變數是否為異質陣列 可用iscell 指令 Ex:iscell01.m C = {[1,2,3]; 'This is a test.'}; iscell(C) ans = 1 上例中,iscell 的執行結果是傳回值 1,代表變數 A 是一個異質陣列,若傳回值 0,則代表不是異質陣列。
將數值陣列轉換成異質陣列 num2cell 指令可將一數值陣列轉換成異質陣列, 其使用語法為: C = num2cell(A, dim)
將數值陣列轉換成異質陣列(cont) Ex:num2cell01.m A = [1 2 3;4 5 6]; % 建立一個數值陣列 A C = num2cell(A) % 將數值陣列 A 轉成異質陣列 C C = [1] [2] [3] [4] [5] [6]
將數值陣列轉換成異質陣列(cont) 可以將上例數值陣列 A 中的每一直行, 轉成異質陣列 D 的元素 Ex::num2cell02.m A = [1 2 3;4 5 6]; % 建立的一個數值陣列 A D = num2cell(A, 1) % 1 代表「橫列被切割」 D = [2x1 double] [2x1 double] [2x1 double
將數值陣列轉換成異質陣列(cont) 也可以將數值陣列 A 的每一橫列, 轉成異質陣列 E 的元素 Ex:num2cell03.m A = [1 2 3;4 5 6]; % 建立的一個數值陣列 A E = num2cell(A, 2) % 2 代表「直行被切割」 E = [1x3 double]
將結構陣列轉換成異質陣列 struct2cell 指令可將一結構陣列的所有欄位值轉換成異質陣列。 Ex:struct2cell01.m student.name = 'Tim'; student.age = 8; %student為一struct sCell = struct2cell(student) sCell = 'Tim' [ 8]
將異質陣列轉換為結構陣列 另外有一個 cell2struct 指令 可以將異質陣列轉換為結構陣列
將結構陣列的某一欄位值轉換成異質陣列 使用 deal 指令 Ex:deal01.m S = struct('name',{'Tim','Annie'},'age', {8,5}); [sCell{1:length(S)}] = deal(S.name) sCell = 'Tim ' 'Annie'
deal 指令 deal 指令的輸入及輸出引數需有相同個數 如上例中,sCell{1:length(S)} 的作用即是產生以逗點分開的輸出變數列。 善用 deal 指令,可達成事半功倍之效, 以下欲列出 MATLAB 根目錄下所有目錄(不含檔案)
Ex: deal02.m dirInfo = dir(matlabroot); % 列出 MATLAB 的根目錄的各種資訊 n = length(dirInfo); % 檔案及目錄的個數 [fileAndDir{1:n}] = deal(dirInfo.name); % fileAndDir 包含檔案及目錄名稱 dirs = fileAndDir([dirInfo.isdir]) % dirs 包含各目錄名稱
Result dirs = Columns 1 through 10 '. ' '..' 'bin' 'demos' 'extern' 'help' 'ja' 'java' 'notebook' 'rtw‘ Columns 11 through 17 'simulink' 'stateflow' 'sys' 'toolbox' 'uninstall' 'webserver' 'work'
本章指令彙整 指令 功能 cellplot(A) celldisp(A) reshape(A,m,n) cell(m,n) iscell(A) 測試變數 A 是否為異質陣列: 傳回值 0,代表不是異質陣列 傳回值 1,代表是異質陣列 num2cell(A, d) 將數值陣列 A 轉成異質陣列,d 表示被切割的維度 struct2cell(A) 將結構陣列 A 的所有欄位名稱值,轉換成異質陣列
Cell array functions Description C = cell(n) C = cell(n,m) celldisp(C) cellplot(C) C = num2cell(A) [X,Y, ...] = deal(A,B, ...) [X,Y, ...] = deal(A) iscell(C) Description Creates an n × n cell array C of empty matrices. Creates an n × m cell array C of empty matrices. Displays the contents of cell array C. Displays a graphical representation of the cell array C. Converts a numeric array A into a cell array C. Matches up the input and output lists. Equivalent to X = A, Y = B, . . . . X = A, Y = A, . . . . Returns a 1 if C is a cell array; otherwise, returns a 0.
請寫一個函數 readFile.m,其用法如下: cellStr = readFile(fileName) 其中,輸入引數 fileName 是一個字串,代表檔案名稱,輸出引數 cellStr 則是一個異值字串陣列,陣列的每一個元素都是一個字串,代表原檔案中的每一列資料。(不可使用 textread 或 fileread 指令來完成本題。) function contents = getfile(fileName); %GETFILE Get the content of a file and put it into a cell string if nargin==0, selfdemo; return; end fid = fopen(fileName); if fid<0, error('Cannot open file!'); end lineNum = 1; while 1 line = fgetl(fid); if ~isstr(line), break, end contents{lineNum} = xlate(line); lineNum = lineNum+1; fclose(fid); % Subfunction for self demo function selfdemo fileName = [mfilename, '.m']; contents = feval(mfilename, fileName); fprintf('The contents of "%s":\n', mfilename); for i=1:length(contents), fprintf('%s\n', contents{i});
split(‘This#is#a#test#string’, ‘#’), 產生的結果應該是 function tokenList = split(str, delimiter) % split: Split a string based on a given delimiter % Usage: % tokenList = split(str, delimiter) if nargin==0; selfdemo; return; end tokenList = {}; remain = str; i = 1; while ~isempty(remain), [token, remain] = strtok(remain, delimiter); tokenList{i} = token; i = i+1; End function selfdemo str='This-is-a-test'; tokenList=feval(mfilename, str, '-'); str fprintf('After running "tokenList=split(str, ''-'')":\n'); tokenList 請寫一個函數 split.m,其用法如下: tokenList = split(str, delimiter), 其中,str 是一個輸入字串,delimiter 則是一個字元,此函數會將 str 依照 delimiter 的位置而拆開來,並將結果放入一個以異質字串陣列 tokenList。 例如,當我們執行 split(‘This#is#a#test#string’, ‘#’), 產生的結果應該是 {'This', 'is', 'a', 'test', 'string.'}。