2012-02-15 8 views
18

Supponiamo di disporre di un struct array arr, in cui ogni elemento ha un gruppo di campi, incluso uno chiamato val. Mi piacerebbe incrementare il campo di ogni elemento val da una certa quantità costante, in questo modo:Aggiornamento di un campo in ogni elemento di un array di strutture Matlab

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

Questo funziona, ovviamente, ma credo che ci dovrebbe essere un modo per fare questo in una sola riga di codice (e non per ciclo continuo). Il meglio che ho trovato è di due righe e richiede una variabile temporanea:

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

Qualche idea? Grazie.

risposta

11

Solo una nota, il deal non è necessario c'è:

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

L'unico altro modo che conosco come fare questo (senza il ciclo foor) sta usando arrayfun per iterare su ogni struttura nella matrice :

% 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) 

che ultime boccole di comando oltre ogni struttura in arr e restituisce uno nuovo in cui s.val è stato impostato su s.val=3.

penso che questo è in realtà meno efficiente di quanto il tuo precedenti due-liner e il ciclo for, però, perché restituisce una copia di arr al contrario di operare sul posto.

(È un peccato che Matlab non supporti l'indicizzazione a strati come [arr.val]=num2cell([arr.val]+3){:}).

+0

Grazie per il suggerimento su "affare". Non sapevo di 'setfield', quindi sembra che lo faccia in una riga, ma come dici tu, questo è sicuramente peggio della soluzione per il ciclo. Per quanto riguarda l'indicizzazione del genere, l'ho esaminata qualche tempo fa; In sostanza, Mathworks sostiene che il supporto di qualcosa di simile imporrebbe modifiche alla parser di incompatibilità della compatibilità. Il che è un peccato, dato che mi infastidisce quasi ogni volta che scrivo un codice Matlab. – Carl

+0

Grazie per questa risposta! In MATLAB 2013b, [arr.val] = newVals {:} funziona MA arr.val = newVals {:}. Cosa fanno esattamente le parentesi in questo caso? –

+0

'arrayfun' è solo un wrapper per un ciclo' for' in MATLAB, quindi tecnicamente stai ancora usando i loop, anche se sotto mentite spoglie. – Adriaan

1

Tutti i campi in quella struttura sono scalari o hanno le stesse dimensioni? Se è così, il modo idiomatico di Matlab è di riorganizzare la propria struct in modo che sia una struttura scalare con array in ciascuno dei suoi campi, invece di una matrice di strutture con valori scalari nei campi. Quindi puoi eseguire operazioni vettoriali sui campi, ad esempio arr.val = arr.val + 3;. Vedi se riesci a riordinare i tuoi dati. Farlo in questo modo è molto più efficiente sia nel tempo che nella memoria; questo è probabilmente il motivo per cui Matlab non fornisce una comoda sintassi per operare su campi di matrici di strutture.

0

se la matrice struct si sta tentando di impostare è un insieme di oggetti grafici (gestisce la linea, maniglie figura, asce maniglie, ecc), allora avete bisogno di utilizzare la funzione 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 
Problemi correlati