¿Cómo puedo indexar una matriz MATLAB devuelta por una función sin asignarla primero a una variable local?


Por ejemplo, si quiero leer el valor medio de magic(5), puedo hacerlo como esto:

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

Para obtener value == 13. Me gustaría poder hacer algo como uno de estos:

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

Para prescindir de la variable intermedia. Sin embargo, MATLAB se queja de Unbalanced or unexpected parenthesis or bracket en el primer paréntesis antes de 3.

¿Es posible leer valores de un array/matriz sin asignarlo primero a una variable?

Author: Jonas Heidelberg, 2010-09-02

9 answers

En realidad es posible hacer lo que quieras, pero tienes que usar la forma funcional del operador de indexación. Cuando realiza una operación de indexación utilizando (), en realidad está haciendo una llamada a la subsref función. Entonces, aunque no puedes hacer esto:

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

Usted puede hacer esto:

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

Feo, pero posible. ;)

En general, solo tiene que cambiar el paso de indexación a una llamada a función para que no tenga dos conjuntos de paréntesis inmediatamente después uno del otro. Otra forma de hacer esto sería definir su propia función anónima para hacer la indexación subíndice. Por ejemplo:

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

Sin embargo, cuando todo está dicho y hecho, la solución temporal de la variable local es mucho más legible, y definitivamente lo que sugeriría.

 342
Author: gnovice,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-04 18:46:47

Solo hubo una buena entrada en el blog en Loren sobre el arte de Matlab hace un par de días con un par de gemas que podrían ayudar. En particular, usando funciones auxiliares como:

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

Donde paren() se puede usar como

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

Volvería

ans = 16

También conjeturo que esto será más rápido que la respuesta de gnovice, pero no lo he comprobado (¡Usa el perfilador!!!). Dicho esto, también tienes que incluir estas definiciones de función en alguna parte. Yo personalmente he hecho las funciones independientes en mi camino, porque son súper útiles.

Estas funciones y otras están ahora disponibles en el complemento Functional Programming Constructs que está disponible a través del Explorador de complementos de MATLAB o en el Intercambio de archivos .

 113
Author: T. Furfaro,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-22 11:44:41

¿Cómo te sientes sobre el uso de características no documentadas:

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

O para matrices de celdas:

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

Al igual que la magia :)


ACTUALIZACIÓN:

Malas noticias, el hack anterior ya no funciona en R2015b! Eso está bien, era una funcionalidad indocumentada y no podemos confiar en ella como una característica compatible:)

Para aquellos que se preguntan dónde encontrar este tipo de cosas, busque en la carpeta fullfile(matlabroot,'bin','registry'). Hay un montón de archivos XML que enumeran todo tipo de golosinas. Ser advirtió que llamar a algunas de estas funciones directamente puede bloquear fácilmente su sesión de MATLAB.

 74
Author: Amro,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-31 07:54:47

Al menos en MATLAB 2013a se puede utilizar getfield me gusta:

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

Para obtener el elemento en (1,2)

 48
Author: Ian M. García,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-30 20:25:46

Desafortunadamente una sintaxis como magic(5)(3,3) no es compatible con matlab. es necesario utilizar variables intermedias temporales. puede liberar la memoria después de su uso, por ejemplo,

tmp = magic(3);
myVar = tmp(3,3);
clear tmp
 15
Author: second,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-09-02 12:46:10

Tenga en cuenta que si compara los tiempos de ejecución con la forma estándar (asigna el resultado y luego accede a las entradas), son exactamente los mismos.

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

En mi opinión, la conclusión es : MATLAB no tiene punteros, tienes que vivir con ello.

 12
Author: titus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-04 18:31:09

Podría ser más simple si haces una nueva función:

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

Y luego usarlo:

value = getElem(magic(5), 3, 3);
 6
Author: Vugar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-05-01 16:58:07

Su notación inicial es la forma más concisa de hacer esto:

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

Si está haciendo esto en un bucle, puede reasignar M cada vez e ignorar la declaración clara también.

 4
Author: Andreas GS,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-08-20 18:16:36

Para complementar la respuesta de Amro, puedes usar feval en lugar de builtin. No hay diferencia, realmente, a menos que intente sobrecargar la función del operador:

BUILTIN(...) es lo mismo que FEVAL(...) excepto que llamará a la versión original incorporada de la función incluso si está sobrecargada existe (para que esto funcione, nunca debes sobrecargar BUILTIN).

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

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

Lo interesante es que feval parece ser un poco más rápido que builtin (en ~3.5%), en menos en Matlab 2013b, que es raro dado que feval necesita verificar si la función está sobrecargada, a diferencia de 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
Author: nirvana-msu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-12 20:54:00