2017-03-08 60 views
2

我有一個函數將一個矢量作爲輸入,使用另一個函數從輸入創建一個導數矢量,然後比較兩個矢量以產生其輸出矢量。我現在有這一個工作循環如下:執行數組運算時不會循環涉及2個矢量的函數

function [parentIndexVec] = computeParentIndex(nameVec) 

    parentNameVec = computeParentName(nameVec); 
    for i=1:length(parentNameVec) 
     parentIndexVec(i) = find(strcmp(nameVec, parentNameVec{i})); 
    end 

end 

computeParentName功能基本返回nameVec副本連同其刪除最後一個字母。循環前的單元陣列然後顯示如下:

nameVec  = '' 'a' 'b' 'aa' 'ab' 'ba' 'aba' 'abb' 
parentNameVec = '' ''  ''  'a'  'a'  'b'  'ab'  'ab' 

該功能的目標是找到的,其中在parentNameVec每個元素出現在nameVec的索引,並且它的輸出因此爲如下:

parentIndexVec = 1  1  1  2  2  3  5  5 

我試圖做一個cellfun來實現這一點,但無法讓它運作,因爲兩個向量必須在每個點進行比較。

我的問題如下:

  1. 有沒有辦法消除的循環來做到這一點?
  2. 在大多數情況下,矩陣運算而不是循環是否真的更快?
  3. 如果是這樣,那麼cellfun在速度上與純矩陣運算進行比較,還是會像循環一樣慢?

感謝您的協助!

回答

1
  1. 您可以使用ismember內找到nameVec

    nameVec = {'' 'a' 'b' 'aa' 'ab' 'ba' 'aba' 'abb'}; 
    parentNameVec = {'' ''  ''  'a'  'a'  'b'  'ab'  'ab'}; 
    
    [~, parentIndexVec] = ismember(parentNameVec, nameVec) 
    % 1 1 1 2 2 3 5 5 
    
  2. 對於矩陣運算在parentNameVec串的出現,操作幾乎可以肯定將是比for循環更快。兩種方法之間的差異隨着時間而減少,但仍然存在。不幸的是,在你的例子中,你正在使用沒有矩陣操作的單元陣列。

  3. cellfun幾乎總是慢於for循環,因爲MATLAB的JIT編譯器能夠更好地優化for循環的內容。在更新版本的MATLAB(R2015b +)中尤其如此,其中執行引擎被重新設計並提供更好的加速度。

之所以這麼說的,內置功能幾乎總是要優於自己的實現算法(用於環路或其他方式),因爲它已被Mathworks公司優化以獲得不俗的表現,強大的錯誤檢查功能,有時會在較低的級別上執行。

+0

我很欣賞這個迴應。確切的我正在尋找的功能!所以,我實際上已經通過我的其他子函數來用'cellfun'替換'for'循環,所以我可能不知不覺地降低了它的效率。大多數使用'cellfun'完成的操作能以更快的矩陣操作方式完成嗎?例如,上面提到的子函數('computeParentName')使用cellfun從'nameVec'單元格數組中刪除每個元素的最後一個字母。有沒有更簡單的方法來做這樣的事情? – teepee

+0

@teepee它真的取決於您要執行的操作的具體細節。對於內置於MATLAB中的字符串的單元陣列進行操作有很多操作。要刪除最後一個字符,我會這樣做:'regexprep(nameVec,'。$','')'只是用空字符串替換最後一個字符。 – Suever

+0

謝謝,我沒有想過在MATLAB中使用正則表達式。非常好,他們可以處理chars和cellstr。這可以避免我寫很多代碼來處理這些區別。雖然我在這裏,你會碰巧知道一個cellstr函數,它返回單元格數組中每個字符串的長度嗎?即'lengthArray = foo({'aaa''bb''a'})'返回'[3 2 1]'? – teepee