2015-12-01 14 views
5

Quindi mi sono chiesto per un po 'di tempo. Riassumendo su alcune variabile di matrice A è facile comesomma MATLAB su tutti gli elementi di espressione con valore di matrice

sum(A(:)) 
% or 
sum(...sum(sum(A,n),n-2)...,1) % where n is the dimension of A 

Tuttavia una volta che si arriva alle espressioni della (:) non funziona più, come

sum((A-2*A)(:)) 

non è la sintassi MATLAB valida, invece abbiamo bisogno di scrivere

foo = A-2*A; 
sum(foo(:)) 
%or the one liner 
sum(sum(...sum(A-2*A,n)...,2),1) % n is the dimension of A 

l'uno di linea sopra funziona solo, se la dimensione di A è fisso, che, a seconda di cosa si sta facendo, non possono necessaria sii il caso Lo svantaggio delle due linee è, che foo sarà tenuto in memoria fino a quando non si esegue clear foo o potrebbe non essere nemmeno possibile a seconda della dimensione di A e cos'altro è nel tuo spazio di lavoro.

Esiste un modo generale per aggirare questo problema e riassumere tutti gli elementi di un'espressione valutata con array in una singola riga/senza creare variabili temporali? Qualcosa come sum(A-2*A,'-all')?

Edit: Si differes da How can I index a MATLAB array returned by a function without first assigning it to a local variable?, in quanto non riguarda in generale (e non specifico) l'indicizzazione di matrice valutate espressioni o valori restituiti, ma piuttosto la somma su ogni indice possibile.

Mentre è possibile risolvere il mio problema con la risposta fornita nel link, gnovice si dice che usare subref è una soluzione piuttosto brutta. Andras Deak ha pubblicato un modo molto più pulito di fare ciò nei commenti qui sotto.

+1

Perché sei così desideroso di evitare la variabile temporanea? Non ha importanza in termini di velocità e anche nessuno in termini di RAM (la stessa variabile verrebbe creata nella chiamata "somma"). Direi che 'sum (sum())' potrebbe essere più veloce, dal momento che rimodellare le matrici di grandi dimensioni richiede molto tempo. – Adriaan

+1

@Daniel Credo che ci sia una semplice risposta a questa domanda che non riguarda il duplicato: 'sum (risagoma (A-2 * A, 1, []))'. Si prega di riaprire se si accetta in modo che io possa rispondere. –

+0

@AndrasDeak Entrambe le versioni funzionano, ma la tua sembra molto più pulita che usare 'subref'. Vale la pena riaprire una domanda in questo caso? (Non sono sicuro del corretto codice di condotta qui.) –

risposta

10

Mentre le risposte a the linked duplicate possono effettivamente essere applicate al problema, l'ambito più ristretto della domanda ci consente di fornire una soluzione molto più semplice rispetto alle risposte fornite.

È possibile sommare tutti gli elementi in un'espressione (tra cui il valore di ritorno di una funzione) da rimodellare la matrice prima di 1d:

sum(reshape(A-2*A,1,[])) 
%or even sum(reshape(magic(3),1,[])) 

Questo sarà rimodellare la tua espressione array-determinata dalla dimensione [1, N] dove N viene ricavato dalla dimensione dell'array, ovvero numel(A-2*A) (ma la sintassi precedente di reshape calcolerà la dimensione mancante per te, non è necessario valutare l'espressione due volte). Quindi una singola chiamata a sum somma tutti gli elementi, se necessario.

Il caso reale dove si deve ricorrere a qualcosa di simile è quando una funzione restituisce un array con un numero imprecisato di dimensioni, e si desidera utilizzare la sua somma in una funzione anonima (facendo temporanea variabili non disponibili):

fun = @() rand(2*ones(1,randi(10))); %function returning random 2 x 2 x ... x 2 array with randi(10) dimensions 
sumfun = @(A) sum(reshape(A,1,[])); 
sumfun(fun()) %use it