如何在不首先将其分配给局部变量的情况下索引函数返回的MATLAB数组?

Joe*_*ney 350 indexing matlab matrix return-value variable-assignment

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

M = magic(5);
value = M(3,3);
Run Code Online (Sandbox Code Playgroud)

得到value == 13.我希望能够做到这样的事情之一:

value = magic(5)(3,3);
value = (magic(5))(3,3);
Run Code Online (Sandbox Code Playgroud)

免除中间变量.然而,MATLAB抱怨Unbalanced or unexpected parenthesis or bracket在第一个括号之前3.

是否可以在不首先将其分配给变量的情况下从数组/矩阵中读取值?

gno*_*ice 377

它实际上可以做到你想要什么,但你必须使用索引操作符的功能形式.使用时执行索引操作时(),实际上是在调用该subsref函数.所以,即使你不能这样做:

value = magic(5)(3, 3);
Run Code Online (Sandbox Code Playgroud)

可以这样做:

value = subsref(magic(5), struct('type', '()', 'subs', {{3, 3}}));
Run Code Online (Sandbox Code Playgroud)

丑陋但可能.;)

通常,您只需将索引步骤更改为函数调用,这样就不会有两组括号紧跟在一起.另一种方法是定义您自己的匿名函数来执行下标索引.例如:

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
Run Code Online (Sandbox Code Playgroud)

然而,当一切都说过和做过临时局部变量的解决方法是很多的可读性,而且肯定我的建议.

  • 这很恶心,但答案非常明确.干得好!应该猜测它会有回来的方式.我想我会继续使用temp变量. (56认同)
  • 请记住,中间变量仍然是完全创建的.因此,如果目的是通过不必创建临时局部变量来节省内存,那就没有运气了. (28认同)
  • 好吧,你知道什么!虽然我同意它非常难看,并且可能不如temp-var解决方案那么可读.+1令人印象深刻的模糊matlab知识! (25认同)
  • @SamRoberts:你不能用像Matlab这样的严格评估语言来解决这个问题.人们想要这个的主要原因是简洁/可读性,而不是节省内存. (8认同)
  • @SamRoberts:是的,但是*确实*可以让你免于在临时(无人曾经做过)上调用`clear`的负担 - 临时性更难延长 (5认同)
  • 这个解决方案可以通过使用`substruct`来改进一点点:`subsref(magic(5),substruct('()',{3,3}))`. (3认同)
  • 精彩的!我在互联网上偶然发现了几个小时!我将坚持使用python。 (2认同)

T. *_*aro 128

只是有好的博客文章罗兰Matlab的艺术前几天有一对夫妇的宝石,这可能有助于.特别是,使用辅助函数,如:

paren = @(x, varargin) x(varargin{:});
curly = @(x, varargin) x{varargin{:}};
Run Code Online (Sandbox Code Playgroud)

在哪里paren()可以使用像

paren(magic(5), 3, 3);
Run Code Online (Sandbox Code Playgroud)

会回来的

ans = 16
Run Code Online (Sandbox Code Playgroud)

我也猜测这会比gnovice的答案更快,但我没有检查过(使用探查器!!!).话虽这么说,你还必须在某处包含这些函数定义.我个人在我的道路上使它们成为独立的功能,因为它们非常有用.

这些函数和其他函数现在可以在Functional Programming Constructs附件中找到,该附加组件可通过MATLAB Add-On Explorer或File Exchange获得.

  • 这是gnovice答案后半部分的更为通用的版本; 也不错. (2认同)
  • @gerrit 抱歉,完全混乱(我不知道您的“attr”是任意的——在 db tb 中明确定义了这样一个字段)。我相信你正在寻找的是 [getfield()](http://www.mathworks.it/it/help/matlab/ref/getfield.html) (2认同)

Amr*_*mro 75

您对使用未记录的功能感觉如何:

>> builtin('_paren', magic(5), 3, 3)               %# M(3,3)
ans =
    13
Run Code Online (Sandbox Code Playgroud)

或者用于单元格数组:

>> builtin('_brace', num2cell(magic(5)), 3, 3)     %# C{3,3}
ans =
    13
Run Code Online (Sandbox Code Playgroud)

就像魔术:)


更新:

坏消息,上面的黑客在R2015b中不再起作用了!没关系,它是未记录的功能,我们不能依赖它作为支持的功能:)

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

  • 冒号(:)运算符必须与撇号"':'`一起使用,以避免错误`未定义函数或变量"内置"`. (2认同)
  • 我不认为有一些方法可以使用`end`吗? (2认同)
  • @knedlsepp:不,不幸的是整个[`end`-trickery](http://www.mathworks.com/help/matlab/matlab_oop/indexed-reference-and-assignment.html#br1dtdk-1)不起作用在这种语法中,你必须明确你的索引...(相同的限制适用于大多数其他列出的答案) (2认同)

小智 53

至少在MATLAB 2013a中你可以使用getfield如下:

a=rand(5);
getfield(a,{1,2}) % etc
Run Code Online (Sandbox Code Playgroud)

得到元素(1,2)

  • @mmumboss:这是未记录的行为,此功能可能会在未来版本中消失,恕不另行通知.除此之外没有缺点. (6认同)
  • 这实际上是一个不错的方法.有什么缺点吗? (5认同)
  • 从MATLAB2017b开始,记录了此功能. (4认同)

sec*_*ond 15

遗憾的magic(5)(3,3)是,matlab不支持语法.你需要使用临时中间变量.你可以在使用后释放内存,例如

tmp = magic(3);
myVar = tmp(3,3);
clear tmp
Run Code Online (Sandbox Code Playgroud)

  • 我们可以在任何地方投票支持添加此功能吗? (2认同)

tit*_*tus 12

请注意,如果您将运行时间与标准方式进行比较(将结果作为对象,然后访问条目),则它们完全相同.

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
Run Code Online (Sandbox Code Playgroud)

我认为,底线是:MATLAB没有指针,你必须忍受它.


Vug*_*gar 6

如果你创建一个新函数可能会更简单:

function [ element ] = getElem( matrix, index1, index2 )
    element = matrix(index1, index2);
end
Run Code Online (Sandbox Code Playgroud)

然后使用它:

value = getElem(magic(5), 3, 3);
Run Code Online (Sandbox Code Playgroud)

  • 是的,更一般的方式,但不友好...在我看来非常难看. (2认同)