实现“卷曲"和“访问"“链接". Matlab中的函数 [英] Implementing 'curly' and 'access' "chaining" functions in matlab
问题描述
I read this article on the mathworks blog about functional programming in matlab, and two of the helper functions there were:
paren = @(x, varargin) x(varargin{:});
curly = @(x, varargin) x{varargin{:}};
完成三重奏(并与五个字母的主题保持一致)的显而易见的第三个人将是:
The obvious third one to complete the trio (and in keeping with the five-letter theme) would be:
acces = @(x, field) x.(field);
除了在matlab中讨论以这种方式实现链接是否是一个好主意的讨论外(注意:默认情况下octave支持链接),paren
似乎效果很好,正如预期的那样;但是,curly
和acces
有一个主要缺点;考虑以下代码:
Putting the discussion of whether it's a good idea to implement chaining in this manner or not in matlab aside (note: octave supports chaining by default), paren
seems to work well, as expected; however, curly
and acces
have a major drawback; consider the following code:
>> C = {1,2,3,4; 2,3,4,5; 3,4,5,6; 4,5,6,7};
>> A = [curly(C, 3, ':')]
A =
3
即预期的序列生成没有发生.
(请注意,此代码可以在Octave中正常运行,即A = [3,4,5,6]
)
i.e. the expected sequence generation didn't happen.
(note that this code works as expected in Octave, i.e. A = [3,4,5,6]
)
同样,acces
在matlab中不会产生序列
Equally, acces
does not produce a sequence in matlab
>> S = [struct('name', 'john'), struct('name', 'jim')];
>> A = {acces(S, 'name')}
A =
'john'
(而Octave产生了预期的A = {'john', 'jim'}
)
(whereas Octave produces the expected A = {'john', 'jim'}
)
我了解,区别可能更多地取决于实现方面. a.函数如何在Matlab和octave中返回内容,和/或 b..是从两种语言的单元格和结构生成的.
I understand that the difference is probably more a matter of implementation in terms of a. how functions return stuff in matlab vs octave, and/or b. how sequences are generated from cells and structs in the two languages.
但是,有没有一种编程方法可以让matlab执行上述预期的操作?
换句话说,是否有一种方法可以定义curly
和acces
函数来像八度一样返回一个序列(匿名函数:p额外的好处)?
PS.我在寻找的答案并不平凡 使用varargout获取多个参数".一个.
PS2.
However, is there a programmatic way to get matlab to perform the intended operation above?
In other words, is there a way to define curly
and acces
functions that return a sequence (extra bonus for anonymous function :p ) like octave does?
PS. The answer I'm looking for is not the trivial "to get multiple arguments out use varargout" one.
PS2.
推荐答案
免责声明:答案更少,一些随机的想法更多
这里的问题是,在MATLAB中,单个函数(匿名函数或其他函数)无法以点引用和{}
索引的方式返回以逗号分隔的列表.
The issue here is that, in MATLAB, a single function (anonymous or otherwise) is incapable of returning a comma-separated list the way that dot referencing and {}
indexing can.
即使MATLAB的内部函数也无法执行引用:
Even MATLAB's internal functions for performing the referencing are incapable of doing so:
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
和其他内置函数返回您希望的多个值的方式
But what a single function can do in MATLAB, is return multiple outputs. This is precisely how subsref
and the other built-ins return the multiple values you're hoping for
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, ':');
现在,这实际上并不能帮助您的助手匿名功能,因为它需要知道需要多少输出,而这又取决于输入.
Now this doesn't really help your helper anonymous function since it requires knowledge of how many outputs to expect and that in turn depends on the inputs.
对于您的acces
函数,直接确定输出数量是相对简单的,因此您可以轻松地执行以下操作:
For your acces
function, it's relatively straight forward to determine the number of outputs so you could easily do something like:
[A{1:numel(S)}] = acces(S, 'name');
不幸的是,您不能在匿名函数中执行此操作,并且除了通过对cell2mat
Unfortunately, you can't do that inside of an anonymous function, and there's also no easy way to get a non-cell array out apart from wrapping this with a follow-up call to cell2mat
[A{1:numel(S)}] = acces(S, 'name');
A = cell2mat(A);
您可以创建一些匿名函数来执行这些各种操作,但是它们很杂乱.
You could create some anonymous functions to do these various operations, but they are messy.
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
遍历它以产生结果.
As for your curly
you could instead use paren
to grab a subset of the cell array as a cell and then loop through it with cellfun
to yield the result.
% This is really just using parenthesis
curly_sequence_cell = paren;
curly_sequence_array = @(varargin)cell2mat(paren(varargin{:}));
但是 real 解决方案只是使用一个临时变量,然后使用典型的MATLAB语法将其编入索引:)
But the real solution is just use a temporary variable and then index into that using the typical MATLAB syntax :)
S = struct('name', {'john', 'jim'});
A = {S.name};
这篇关于实现“卷曲"和“访问"“链接". Matlab中的函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!