seleccionar - ¿Cómo puedo indexar una matriz MATLAB devuelta por una función sin asignarla primero a una variable local?
seleccionar elementos de una matriz matlab (9)
¿Cómo te sientes acerca del uso de características no documentadas:
>> builtin(''_paren'', magic(5), 3, 3) %# M(3,3)
ans =
13
o para matrices de células:
>> builtin(''_brace'', num2cell(magic(5)), 3, 3) %# C{3,3}
ans =
13
Al igual que la magia :)
ACTUALIZAR:
¡Malas noticias, el truco anterior ya no funciona en R2015b ! Eso está bien, era una funcionalidad no documentada y no podemos confiar en ella como una función 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. Tenga en cuenta que llamar directamente a algunas de estas funciones puede bloquear fácilmente su sesión de MATLAB.
Por ejemplo, si quiero leer el valor medio de magic(5)
, puedo hacerlo así:
M = magic(5);
value = M(3,3);
para obtener un 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 del 3
.
¿Es posible leer valores de una matriz / matriz sin asignarlos primero a una variable?
Al menos en MATLAB 2013a puedes usar getfield
como:
a=rand(5);
getfield(a,{1,2}) % etc
para obtener el elemento en (1,2)
En realidad, es posible hacer lo que quiera, pero debe usar la forma funcional del operador de indexación. Cuando realiza una operación de indexación usando ()
, en realidad está haciendo una llamada a la función de subsref
. Entonces, aunque no puedas 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 de función para que no tenga dos conjuntos de paréntesis inmediatamente uno tras otro. Otra forma de hacer esto sería definir su propia función anónima para realizar la indexación con subíndices. 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 de la variable local temporal es mucho más legible, y definitivamente lo que sugeriría.
Hace un par de días hubo una buena publicación de blog sobre Loren en el Arte de Matlab con un par de gemas que podrían ayudar. En particular, usando funciones de ayuda como:
paren = @(x, varargin) x(varargin{:});
curly = @(x, varargin) x{varargin{:}};
donde paren()
se puede utilizar como
paren(magic(5), 3, 3);
volvería
ans = 16
También supongo que esto será más rápido que la respuesta de gnovice, pero no lo he comprobado (¡¡¡Use el perfilador !!!). Dicho esto, también debes incluir estas definiciones de funciones en algún lugar. Personalmente los he hecho funciones independientes en mi camino, porque son super útiles.
Estas y otras funciones ahora están disponibles en el complemento de construcciones de programación funcional que está disponible a través del complemento MATLAB o en el intercambio de archivos .
Para complementar la respuesta de Amro, puedes usar feval
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 incorporada original de la función, incluso si existe una sobrecargada (para que esto funcione, nunca debe 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 solo un poquito más rápido que builtin
(en ~ 3.5%), al menos en Matlab 2013b, lo cual es extraño 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.
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);
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, simplemente puede reasignar M cada vez e ignorar la declaración clara también.
Tenga en cuenta que si compara los tiempos de ejecución con la forma estándar (asigne el resultado y luego acceda a las entradas), serán exactamente iguales.
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, tiene que vivir con eso.
desafortunadamente la sintaxis como magic(5)(3,3)
no es compatible con matlab. necesitas usar variables intermedias temporales puede liberar la memoria después de su uso, por ejemplo,
tmp = magic(3);
myVar = tmp(3,3);
clear tmp