我如何索引一个函数返回的MATLAB数组,而不首先将其分配给一个局部变量?

例如,如果我想从magic(5)读取中间值,我可以这样做:

M = magic(5);
value = M(3,3);

来获得value == 13。我希望能够做一些像这样的事情:

value = magic(5)(3,3);
value = (magic(5))(3,3);

省略中间变量。然而,MATLAB抱怨Unbalanced or unexpected parenthesis or bracket3之前的第一个括号上。

是否有可能从数组/矩阵读取值,而不首先分配给一个变量?

77233 次浏览

不幸的是,matlab不支持magic(5)(3,3)这样的语法。您需要使用临时中间变量。你可以在使用后释放内存。

tmp = magic(3);
myVar = tmp(3,3);
clear tmp

它实际上可以做你想做的事情,但你必须使用索引操作符的函数形式。当你使用()执行索引操作时,你实际上是在调用subsref函数。所以,即使你不能这样做:

value = magic(5)(3, 3);

可以这样做:

value = subsref(magic(5), struct('type', '()', 'subs', \{\{3, 3}}));

丑陋,但有可能。;)

一般来说,只需将索引步骤更改为函数调用,这样就不会有两组括号紧跟着另一组括号。另一种方法是定义你自己的匿名函数来做下标索引。例如:

subindex = @(A, r, c) A(r, c);     % An anonymous function for 2-D indexing
value = subindex(magic(5), 3, 3);  % Use the function to index the matrix

然而,当所有这些都说了,做了,临时局部变量解决方案是更具可读性,这肯定是我所建议的。

注意,如果比较运行时间与标准方式(给结果赋值,然后访问条目),它们是完全相同的。

subs=@(M,i,j) M(i,j);
>> for nit=1:10;tic;subs(magic(100),1:10,1:10);tlap(nit)=toc;end;mean(tlap)


ans =


0.0103


>> for nit=1:10,tic;M=magic(100); M(1:10,1:10);tlap(nit)=toc;end;mean(tlap)


ans =


0.0101

在我看来,底线是:MATLAB没有指针,你必须接受它。

你的初始符号是最简洁的方法:

M = magic(5);  %create
value = M(3,3);  % extract useful data
clear M;  %free memory

如果你在循环中这样做,你可以每次都重新分配M,并忽略clear语句。

几天前,在Loren讲Matlab的艺术上只有好博文,其中有一些宝石可能会有所帮助。特别是,使用helper函数,如:

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

paren()可以像

paren(magic(5), 3, 3);

将返回

ans = 16

我也会猜测这将比g新手的答案更快,但我没有检查(使用分析器!!)。也就是说,你还必须在某个地方包含这些函数定义。我个人把它们作为独立的函数,因为它们非常有用。

这些函数和其他函数现在可以在函数式编程结构插件中使用,该插件可以通过MATLAB插件资源管理器或文件交换上使用。

你对使用未记录的特性有什么看法:

>> builtin('_paren', magic(5), 3, 3)               %# M(3,3)
ans =
13

或者对于单元格数组:

>> builtin('_brace', num2cell(magic(5)), 3, 3)     %# C{3,3}
ans =
13

就像魔法一样:)


更新:

坏消息,上面的黑客不再工作R2015b!没关系,它是没有文档的功能,我们不能依赖它作为一个受支持的功能:)

对于那些想知道在哪里可以找到这类东西的人,请查看文件夹fullfile(matlabroot,'bin','registry')。这里有一堆XML文件列出了各种各样的好东西。请注意,直接调用其中一些函数很容易使MATLAB会话崩溃。

如果你创建一个新函数,它会更简单:

function [ element ] = getElem( matrix, index1, index2 )
element = matrix(index1, index2);
end

然后使用它:

value = getElem(magic(5), 3, 3);

至少在MATLAB 2013a中,你可以像这样使用getfield:

a=rand(5);
getfield(a,{1,2}) % etc

得到(1,2)点的元素

为了补充Amro的回答,你可以用feval代替builtin。实际上没有区别,除非你尝试重载运算符函数:

BUILTIN(…)与FEVAL(…)相同,只是它将调用 该函数的原始内置版本,即使是重载版本 存在(为了使其工作,您必须永远不要过载 内装式). < / p >

>> feval('_paren', magic(5), 3, 3)               % M(3,3)
ans =
13


>> feval('_brace', num2cell(magic(5)), 3, 3)     % C{3,3}
ans =
13

有趣的是,feval似乎只比builtin快一点点(约3.5%),至少在Matlab 2013b中是这样,这很奇怪,因为feval需要检查函数是否重载,而不像builtin:

>> tic; for i=1:1e6, feval('_paren', magic(5), 3, 3); end; toc;
Elapsed time is 49.904117 seconds.
>> tic; for i=1:1e6, builtin('_paren', magic(5), 3, 3); end; toc;
Elapsed time is 51.485339 seconds.