Supongamos que tengo un struct matriz arr, donde cada elemento tiene un montón de campos, incluyendo una que se llama val. Me gustaría incremento de cada elemento val campo por algunos cantidad constante, así:

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

Obviamente, esto funciona, pero creo que debería haber una forma para hacer esto en una sola línea de código (y no para el bucle). La mejor que me he encontrado con dos líneas y requiere de una variable temp:

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

Alguna idea? Gracias.

InformationsquelleAutor Carl | 2012-02-15

3 Comentarios

  1. 11

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

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

    La otra única manera que sé cómo hacer esto (sin celebrar un bucle) es el uso de arrayfun para iterar sobre cada estructura en 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)

    Este último comando se repite a lo largo de cada estructura en arr y devuelve una nueva donde s.val se ha establecido para s.val=3.

    Creo que este es menos eficiente que sus dos anteriores-liner y el bucle for, sin embargo, porque devuelve un copia de arr en oposición a los de funcionamiento en el lugar.

    (Es una lástima que Matlab no admite capas de indexación como [arr.val]=num2cell([arr.val]+3){:}).

    • Gracias por la punta en deal. Yo no sabía acerca de setfield, por lo que parece hacerlo en una sola línea, pero como dices, esto sin duda es peor que la solución de circuito. Como para la indización de eso, me miraba en él hace un tiempo; básicamente, Mathworks afirma que el apoyo a cualquier cosa, como que la fuerza de compatibilidad-cambios recientes en el analizador. Lo cual es una lástima, ya que me molesta casi cada vez que puedo escribir cualquier código de Matlab.
    • Gracias por esta respuesta! En MATLAB 2013b, [arr.val] = newVals{:} funciona, PERO arr.val = newVals{:}. ¿Qué es exactamente lo de los corchetes hacer en este caso?
    • arrayfun es simplemente un contenedor para un for bucle en MATLAB, por lo que técnicamente, usted todavía está utilizando bucles, aunque en el disfraz.
    • Una situación donde la oferta es útil con una estructura de matriz es cuando se desea asignar el mismo valor a un campo de cada elemento de la estructura de la matriz. Por ejemplo, si v = 9, puede escribir [arr.val] = deal(v); para asignar 9 al campo val de cada elemento de la estructura de la matriz de arr.
    • [arr.val] = newVals{:}; funciona, pero [arr.val] = newVals(:); no – es que si newVals es un vector y no un cellarray. Puede alguien explicar?!
  2. 1

    Son todos los campos en que se estructura escalar, o del mismo tamaño? Si es así, el idiomáticas Matlab manera de hacer esto es la de reorganizar su estructura para ser un escalar struct con matrices en cada uno de sus campos, en lugar de un array de structs con valores escalares en los campos. A continuación, puede hacer vectorizados operaciones en los campos, como arr.val = arr.val + 3;. A ver si puedes cambiar tus datos. Hacerlo de esta manera es mucho más eficiente en el tiempo y en la memoria; esa es probablemente la razón por la que Matlab no proporcionar conveniente sintaxis para la operación a través de los campos de arrays de estructuras.

  3. 0

    si la estructura de la matriz que están tratando de establecer es un conjunto de objetos gráficos (línea de tiradores, la figura de asas, los ejes de las manijas, etc), entonces usted necesita para 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

Dejar respuesta

Please enter your comment!
Please enter your name here