2012-02-15 14 views
18

Supongamos que tengo una matriz de estructura arr, donde cada elemento tiene un grupo de campos, incluyendo uno llamado val. Me gustaría incrementar val ámbito de cada elemento por una cierta cantidad constante, así:Actualizando un campo en cada elemento de una matriz Matlab struct

for i = 1:length(arr) 
    arr(i).val = arr(i).val + 3; 
end 

Esto funciona obviamente, pero me siento debe haber una manera de hacer esto en una sola línea de código (y no por lazo). El mejor que he encontrado es con dos líneas y requiere una variable temporal:

newVals = num2cell([arr.val] + 3); 
[arr.val] = deal(newVals{:}); 

¿Alguna idea? Gracias.

Respuesta

11

Sólo una nota, la deal no es necesario llegar:

[arr.val] = newVals{:}; % achieves the same as deal(newVals{:}) 

La única manera que sé cómo hacer esto (y sin el bucle Foor) está utilizando arrayfun para iterar sobre cada estructura de la matriz :

% make a struct array 
arr = [ struct('val',0,'id',1), struct('val',0,'id',2), struct('val',0,'id',3) ] 

% some attempts 
[arr.val]=arr.val; % fine 
[arr.val]=arr.val+3; % NOT fine :(

% works ! 
arr2 = arrayfun(@(s) setfield(s,'val',s.val+3),arr) 

que los bucles de comando últimos sobre cada estructura en arr y devuelve una nueva en la s.val se ha establecido en s.val=3.

creo que esto es en realidad menos eficiente que el de dos revestimiento anterior y el bucle sin embargo, porque devuelve una copia de arr en lugar de operar en el lugar.

(Es una pena que Matlab no sea compatible con la indexación en capas como [arr.val]=num2cell([arr.val]+3){:}).

+0

Gracias por la consejo sobre 'trato'. No sabía sobre 'setfield', así que parece hacerlo en una línea, pero como dices, esto es ciertamente peor que la solución for-loop. En cuanto a la indexación de esa manera, la analicé hace un tiempo; Básicamente, Mathworks afirma que el soporte de algo así forzará cambios de compatibilidad al analizador. Lo cual es una pena, ya que me molesta casi cada vez que escribo cualquier código de Matlab. – Carl

+0

¡Gracias por esta respuesta! En MATLAB 2013b, [arr.val] = newVals {:} funciona PERO arr.val = newVals {:}. ¿Qué hacen exactamente los corchetes en este caso? –

+0

'arrayfun' es solo un contenedor para un bucle' for' en MATLAB, por lo que técnicamente todavía está utilizando bucles, aunque disfrazado. – Adriaan

1

¿Todos los campos de esa estructura son escalares o del mismo tamaño? Si es así, la forma idiomática de Matlab para hacer esto es reorganizar su estructura para que sea una estructura escalar con matrices en cada uno de sus campos, en lugar de una matriz de estructuras con valores escalares en los campos. Luego puede hacer operaciones vectorizadas en los campos, como arr.val = arr.val + 3;. Vea si puede reorganizar sus datos. Hacerlo de esta manera es mucho más eficiente en tiempo y memoria; esa es probablemente la razón por la que Matlab no proporciona una sintaxis conveniente para operar sobre campos de matrices de estructuras.

0

si la matriz de estructura que está tratando de establecer es un conjunto de objetos gráficos (se encarga de la línea, se ocupa de la figura, hachas mangos, etc), entonces es necesario utilizar la función set:

x = (1:10)'; 
Y = rand(10,5); 
l = plot(x,Y,'-k'); % returns an array of line handles in l 
set(l,'Color','r'); % sets the property 'Color' for all the five lines in l 
Cuestiones relacionadas