在單元格和陣列上執行的有用函式

這個簡單的例子提供了一些解釋,我發現自從我開始使用 MATLAB 以來非常有用的一些函式:cellfunarrayfun。我們的想法是獲取一個陣列或單元類變數,遍歷其所有元素並在每個元素上應用專用函式。應用函式可以是匿名的,通常是一種情況,也可以是* .m 檔案中定義的任何常規函式。

讓我們從一個簡單的問題開始,並說我們需要找到給定該資料夾的* .mat 檔案列表。對於此示例,首先讓我們在當前資料夾中建立一些* .mat 檔案:

for n=1:10; save(sprintf('mymatfile%d.mat',n)); end

執行程式碼後,應該有 10 個副檔名為* .mat 的新檔案。如果我們執行命令列出所有* .mat 檔案,例如:

mydir = dir('*.mat');

我們應該得到一個 dir 結構元素的陣列; MATLAB 應該給出一個類似的輸出:

10x1 struct array with fields:
    name
    date
    bytes
    isdir
    datenum

如你所見,此陣列的每個元素都是一個包含幾個欄位的結構。所有資訊對於每個檔案確實很重要,但在 99%中我對檔名很感興趣而沒有別的。為了從結構陣列中提取資訊,我曾經建立了一個本地函式,它涉及建立正確大小的時間變數,for 迴圈,從每個元素中提取名稱,並將其儲存到建立的變數中。實現完全相同結果的更簡單方法是使用上述功能之一:

mydirlist = arrayfun(@(x) x.name, dir('*.mat'), 'UniformOutput', false)
mydirlist = 
    'mymatfile1.mat'
    'mymatfile10.mat'
    'mymatfile2.mat'
    'mymatfile3.mat'
    'mymatfile4.mat'
    'mymatfile5.mat'
    'mymatfile6.mat'
    'mymatfile7.mat'
    'mymatfile8.mat'
    'mymatfile9.mat'

這個功能如何運作?它通常需要兩個引數:一個函式控制代碼作為第一個引數和一個陣列。然後,函式將對給定陣列的每個元素進行操作。第三和第四個引數是可選的但很重要。如果我們知道輸出不是常規輸出,則必須將其儲存在單元格中。必須指出將 false 設定為 UniformOutput。預設情況下,此函式會嘗試返回常規輸出,例如數字向量。例如,讓我們提取有關每個檔案佔用多少磁碟空間的資訊(以位元組為單位):

mydirbytes = arrayfun(@(x) x.bytes, dir('*.mat'))
mydirbytes =
       34560
       34560
       34560
       34560
       34560
       34560
       34560
       34560
       34560
       34560

或千位元組:

mydirbytes = arrayfun(@(x) x.bytes/1024, dir('*.mat'))
mydirbytes =
   33.7500
   33.7500
   33.7500
   33.7500
   33.7500
   33.7500
   33.7500
   33.7500
   33.7500
   33.7500

這次輸出是 double 的常規向量。UniformOutput 預設設定為 true

cellfun 是一個類似的功能。這個函式和 arrayfun 之間的區別在於 cellfun 對單元類變數進行操作。如果我們希望僅在單元格’mydirlist’中提取檔名列表中的名稱,我們只需要按如下方式執行此函式:

mydirnames = cellfun(@(x) x(1:end-4), mydirlist, 'UniformOutput', false)
mydirnames = 
    'mymatfile1'
    'mymatfile10'
    'mymatfile2'
    'mymatfile3'
    'mymatfile4'
    'mymatfile5'
    'mymatfile6'
    'mymatfile7'
    'mymatfile8'
    'mymatfile9'

同樣,由於輸出不是常規數字向量,因此輸出必須儲存在單元格變數中。

在下面的示例中,我將兩個函式合併為一個,並僅返回沒有副檔名的檔名列表:

cellfun(@(x) x(1:end-4), arrayfun(@(x) x.name, dir('*.mat'), 'UniformOutput', false), 'UniformOutput', false)
ans = 
    'mymatfile1'
    'mymatfile10'
    'mymatfile2'
    'mymatfile3'
    'mymatfile4'
    'mymatfile5'
    'mymatfile6'
    'mymatfile7'
    'mymatfile8'
    'mymatfile9'

它很瘋狂但很可能因為 arrayfun 返回了一個預期輸入 cellfun 的單元格; 對此的一個注意事項是,我們可以通過將 UniformOutput 設定為 false 來強制顯式地將任何這些函式返回到單元格變數中。我們總能在單元格中獲得結果。我們可能無法在常規向量中獲得結果。

還有一個類似的函式在欄位上執行一個結構:structfun。我沒有特別發現它和其他兩個一樣有用但在某些情況下它會發光。例如,如果想知道哪些欄位是數字或非數字,則以下程式碼可以給出答案:

structfun(@(x) ischar(x), mydir(1))

dir 結構的第一個和第二個欄位是 char 型別。因此,輸出是:

 1
 1
 0
 0
 0

此外,輸出是 true / false 的邏輯向量。因此,它是常規的,可以儲存在向量中; 不需要使用單元格類。