2016-09-21 19 views
3

我在MathWorks公司博客關於MATLAB函數式編程閱讀this article,以及兩個輔助功能有:實施「花」和「訪問」「鏈接」功能的MATLAB

paren = @(x, varargin) x(varargin{:}); 
curly = @(x, varargin) x{varargin{:}}; 

明顯的第三個完成三重奏(並與五個字母的主題保持一致)是:

acces = @(x, field) x.(field); 

把它是否是實現這種方式還是不能在MATLAB一邊(注意鏈是一個好主意的討論:八度支持鏈接默認),paren如預期的那樣似乎運作良好;然而,curlyacces有一個主要缺點;考慮下面的代碼:

>> C = {1,2,3,4; 2,3,4,5; 3,4,5,6; 4,5,6,7}; 
>> A = [curly(C, 3, ':')] 
A = 
    3 

即預期序列代並沒有發生。
(注意,此代碼將按預期在八度,即A = [3,4,5,6]

同樣,acces不會在MATLAB產生序列

>> S = [struct('name', 'john'), struct('name', 'jim')]; 
>> A = {acces(S, 'name')} 
A = 
    'john' 

(而倍頻產生預期A = {'john', 'jim'}

我瞭解這種差異可能更多的是在執行方面的問題a。函數如何返回matlab vs octave中的內容,和/或b。如何從兩種語言的單元格和結構中生成序列。

但是,有沒有一種程序化的方式來讓matlab執行上面的預期操作?
換句話說,有沒有一種方法可以定義curlyacces函數返回一個序列(額外獎金爲匿名函數:p)像八度呢?


PS。我正在尋找的答案不是微不足道的 「獲取多個參數使用可變參數」之一。
PS2。 我在Matlab 2013b上測試了這個,所以我不知道這個行爲是否已經在後來的版本中「固定」(儘管我非常懷疑它)。http://matlab.mathworks.com

回答

4

聲明在測試了最新的MATLAB在線:回答的更小,更有些隨意沉思的

這裏的問題是,在MATLAB,單一的功能(匿名或其他)是無能的以點引用和索引方式返回逗號分隔列表。

即使MATLAB對執行引用內部功能是不能這樣做的:

subsref(S, substruct('.', 'name')) 
% john 

builtin('_dot', S, 'name')    % Only works pre-2015b 
% jim 

subsref(C, substruct('{}', {3 ':'})) 
% 3 

builtin('_brace', C, 3, ':')   % Only works pre-2015b 
% 3 

什麼功能單一可以在MATLAB做的,就是返回多個輸出。這正是如何subsref和其他內建返回你希望多值

S = struct('name', {'john', 'jim'}); 

[val1, val2] = subsref(S, substruct('.', 'name')); 
[val1, val2] = builtin('_dot', S, 'name'); 

C = num2cell(magic(3)); 

[val1, val2, val3] = subsref(C, substruct('{}', {3, ':'})); 
[val1, val2, val3] = builtin('_brace', C, 3, ':'); 

現在,這並不能真正幫助你的助手匿名函數,因爲它需要多少產出預期和知識這又取決於投入。

爲了您acces功能,它是相對簡單的,確定輸出的數量,所以你可以很容易地做一些事情,如:

[A{1:numel(S)}] = acces(S, 'name'); 

不幸的是,你不能做的匿名函數裏面,並有也沒有簡單的方法來從後續調用這個包裹得到一個非單元陣列出拆開來cell2mat

[A{1:numel(S)}] = acces(S, 'name'); 
A = cell2mat(A); 

可以創造一些anonymo我們的功能是做這些不同的操作,但是它們很混亂。

access_cell = @(s,n)arrayfun(@(x)acces(x,n), s, 'uniform', 0); 
access_array = @(s,n)arrayfun(@(x)acces(x,n), s, 'uniform', 1); 

至於你curly你也可以使用paren通過它來抓取單元陣列作爲細胞的一個子集,然後循環使用cellfun產生的結果。

% This is really just using parenthesis 
curly_sequence_cell = paren; 

curly_sequence_array = @(varargin)cell2mat(paren(varargin{:})); 

真正解決方案只需使用一個臨時變量,然後索引,使用MATLAB典型語法:)

S = struct('name', {'john', 'jim'}); 
A = {S.name}; 
+0

我不知道「_dot」和「_brace」 ,知道這很酷! 也謝謝你糾正我的結構語法,我沒有費心查找它,哈哈。儘管我猜想,很好的解決方法會使可讀性比'paren'和'curly'更糟糕,這已經足夠令人質疑了......在matlab中沒有辦法避免那個血腥的臨時變量,是否存在:p –

+0

still,I不知道matlab如何從引擎蓋下的單元/結構創建序列,以便它在直接調用時工作,但不在用subsref調用時工作。當我嘗試使用subsref並且它不工作時,我感到非常驚訝...直到那時,我的印象是()和{}索引只是subsref的語法糖......(例如,在octave,subsref,按預期工作並返回一個序列) –

+1

@TasosPapastylianou通過'subsref'做了更多的探索,並在我的答案中添加了一些信息。雖然你可以強制使用'subsref'來給你所有的值,但是仍然不容易得到逗號分隔列表。 – Suever