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

时间:2021-09-12 23:48:05

For example, if I want to read the middle value from magic(5), I can do so like this:

举个例子,如果我想从魔法(5)中读出中间值,我可以这样做:

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

to get value == 13. I'd like to be able to do something like one of these:

得到值== 13。我希望能做一些类似的事情:

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

to dispense with the intermediate variable. However, MATLAB complains about Unbalanced or unexpected parenthesis or bracket on the first parenthesis before the 3.

省略中间变量。然而,MATLAB在第3个括号前的第一个括号中,对不平衡或意外的括号或括号表示不满。

Is it possible to read values from an array/matrix without first assigning it to a variable?

是否可以从数组/矩阵中读取值而不首先将其赋值给变量?

9 个解决方案

#1


331  

It actually is possible to do what you want, but you have to use the functional form of the indexing operator. When you perform an indexing operation using (), you are actually making a call to the subsref function. So, even though you can't do this:

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

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

You can do this:

你可以这样做:

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

Ugly, but possible. ;)

丑,但可能。,)

In general, you just have to change the indexing step to a function call so you don't have two sets of parentheses immediately following one another. Another way to do this would be to define your own anonymous function to do the subscripted indexing. For example:

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

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

However, when all is said and done the temporary local variable solution is much more readable, and definitely what I would suggest.

然而,当所有这些都被说出来并完成时,临时的局部变量解决方案可读性更强,而且绝对是我所建议的。

#2


108  

There was just good blog post on Loren on the Art of Matlab a couple days ago with a couple gems that might help. In particular, using helper functions like:

几天前,罗兰在Matlab上写了一篇很好的博客文章,上面有一些可能会有用的宝石。特别是,使用helper函数,例如:

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

where paren() can be used like

在哪里可以使用paren() ?

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

would return

将返回

ans = 16

I would also surmise that this will be faster than gnovice's answer, but I haven't checked (Use the profiler!!!). That being said, you also have to include these function definitions somewhere. I personally have made them independent functions in my path, because they are super useful.

我也会猜测这将比g初学者的答案更快,但我没有检查(使用profiler!!! !)也就是说,你还必须在某处包含这些函数定义。我个人使它们在我的路径中独立,因为它们非常有用。

These functions and others are now available in the Functional Programming Constructs add-on which is available through the MATLAB Add-On Explorer or on the File Exchange.

这些函数和其他功能现在可以在函数式编程构造附加组件中使用,该附加组件可以通过MATLAB插件资源管理器或文件交换获得。

#3


73  

How do you feel about using undocumented features:

您如何看待使用未归档的特性:

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

or for cell arrays:

或细胞数组:

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

Just like magic :)

就像魔法:)


UPDATE:

Bad news, the above hack doesn't work anymore in R2015b! That's fine, it was undocumented functionality and we cannot rely on it as a supported feature :)

坏消息,上面的hack在R2015b已经不工作了!这很好,它是无文档的功能,我们不能依赖它作为支持的特性:)

For those wondering where to find this type of thing, look in the folder fullfile(matlabroot,'bin','registry'). There's a bunch of XML files there that list all kinds of goodies. Be warned that calling some of these functions directly can easily crash your MATLAB session.

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

#4


42  

At least in MATLAB 2013a you can use getfield like:

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

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

to get the element at (1,2)

要得到元素at (1,2)

#5


15  

unfortunately syntax like magic(5)(3,3) is not supported by matlab. you need to use temporary intermediate variables. you can free up the memory after use, e.g.

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

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

#6


12  

Note that if you compare running times with the standard way (asign the result and then access entries), they are exactly the same.

请注意,如果您将运行时间与标准方法进行比较(asign结果和访问条目),它们是完全相同的。

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

To my opinion, the bottom line is : MATLAB does not have pointers, you have to live with it.

依我看来,底线是:MATLAB没有指针,你不得不忍受它。

#7


6  

It could be more simple if you make a new function:

如果你做一个新的函数,它可能会更简单:

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

and then use it:

然后使用它:

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

#8


4  

Your initial notation is the most concise way to do this:

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

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

If you are doing this in a loop you can just reassign M every time and ignore the clear statement as well.

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

#9


1  

To complement Amro's answer, you can use feval instead of builtin. There is no difference, really, unless you try to overload the operator function:

为了补充银行的答案,你可以使用feval而不是builtin。没有区别,除非你试图重载运算符函数:

BUILTIN(...) is the same as FEVAL(...) except that it will call the original built-in version of the function even if an overloaded one exists (for this to work, you must never overload BUILTIN).

BUILTIN(…)与FEVAL(…)相同,只是它会调用函数的原始内置版本,即使存在重载的函数(为了工作,也不能重载BUILTIN)。

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

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

What's interesting is that feval seems to be just a tiny bit quicker than builtin (by ~3.5%), at least in Matlab 2013b, which is weird given that feval needs to check if the function is overloaded, unlike builtin:

有趣的是,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.

#1


331  

It actually is possible to do what you want, but you have to use the functional form of the indexing operator. When you perform an indexing operation using (), you are actually making a call to the subsref function. So, even though you can't do this:

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

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

You can do this:

你可以这样做:

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

Ugly, but possible. ;)

丑,但可能。,)

In general, you just have to change the indexing step to a function call so you don't have two sets of parentheses immediately following one another. Another way to do this would be to define your own anonymous function to do the subscripted indexing. For example:

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

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

However, when all is said and done the temporary local variable solution is much more readable, and definitely what I would suggest.

然而,当所有这些都被说出来并完成时,临时的局部变量解决方案可读性更强,而且绝对是我所建议的。

#2


108  

There was just good blog post on Loren on the Art of Matlab a couple days ago with a couple gems that might help. In particular, using helper functions like:

几天前,罗兰在Matlab上写了一篇很好的博客文章,上面有一些可能会有用的宝石。特别是,使用helper函数,例如:

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

where paren() can be used like

在哪里可以使用paren() ?

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

would return

将返回

ans = 16

I would also surmise that this will be faster than gnovice's answer, but I haven't checked (Use the profiler!!!). That being said, you also have to include these function definitions somewhere. I personally have made them independent functions in my path, because they are super useful.

我也会猜测这将比g初学者的答案更快,但我没有检查(使用profiler!!! !)也就是说,你还必须在某处包含这些函数定义。我个人使它们在我的路径中独立,因为它们非常有用。

These functions and others are now available in the Functional Programming Constructs add-on which is available through the MATLAB Add-On Explorer or on the File Exchange.

这些函数和其他功能现在可以在函数式编程构造附加组件中使用,该附加组件可以通过MATLAB插件资源管理器或文件交换获得。

#3


73  

How do you feel about using undocumented features:

您如何看待使用未归档的特性:

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

or for cell arrays:

或细胞数组:

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

Just like magic :)

就像魔法:)


UPDATE:

Bad news, the above hack doesn't work anymore in R2015b! That's fine, it was undocumented functionality and we cannot rely on it as a supported feature :)

坏消息,上面的hack在R2015b已经不工作了!这很好,它是无文档的功能,我们不能依赖它作为支持的特性:)

For those wondering where to find this type of thing, look in the folder fullfile(matlabroot,'bin','registry'). There's a bunch of XML files there that list all kinds of goodies. Be warned that calling some of these functions directly can easily crash your MATLAB session.

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

#4


42  

At least in MATLAB 2013a you can use getfield like:

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

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

to get the element at (1,2)

要得到元素at (1,2)

#5


15  

unfortunately syntax like magic(5)(3,3) is not supported by matlab. you need to use temporary intermediate variables. you can free up the memory after use, e.g.

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

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

#6


12  

Note that if you compare running times with the standard way (asign the result and then access entries), they are exactly the same.

请注意,如果您将运行时间与标准方法进行比较(asign结果和访问条目),它们是完全相同的。

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

To my opinion, the bottom line is : MATLAB does not have pointers, you have to live with it.

依我看来,底线是:MATLAB没有指针,你不得不忍受它。

#7


6  

It could be more simple if you make a new function:

如果你做一个新的函数,它可能会更简单:

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

and then use it:

然后使用它:

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

#8


4  

Your initial notation is the most concise way to do this:

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

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

If you are doing this in a loop you can just reassign M every time and ignore the clear statement as well.

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

#9


1  

To complement Amro's answer, you can use feval instead of builtin. There is no difference, really, unless you try to overload the operator function:

为了补充银行的答案,你可以使用feval而不是builtin。没有区别,除非你试图重载运算符函数:

BUILTIN(...) is the same as FEVAL(...) except that it will call the original built-in version of the function even if an overloaded one exists (for this to work, you must never overload BUILTIN).

BUILTIN(…)与FEVAL(…)相同,只是它会调用函数的原始内置版本,即使存在重载的函数(为了工作,也不能重载BUILTIN)。

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

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

What's interesting is that feval seems to be just a tiny bit quicker than builtin (by ~3.5%), at least in Matlab 2013b, which is weird given that feval needs to check if the function is overloaded, unlike builtin:

有趣的是,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.