2015-12-01 15 views
5

Więc zastanawiam się o tym od dłuższego czasu. Reasumując nad jakimś tablicy zmiennej A jest tak proste jakMATLAB suma wszystkich elementów tablicy wycenione wyrażenie

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

Jednak gdy dojdzie do wyrażeniami (:) już nie działa, jak

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

ma prawidłowej składni Matlab, zamiast musimy napisz

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 

Powyższy liner będzie działał tylko wtedy, gdy wymiar A jest ustalony, co w zależności od tego, co robisz, może nie być konieczne być w tym przypadku. Wadą tych dwóch linii jest to, że foo będzie przechowywane w pamięci aż do uruchomienia clear foo lub może nie być nawet możliwe w zależności od rozmiaru A i tego, co jeszcze jest w twoim obszarze roboczym.

Czy istnieje ogólny sposób na obejście tego problemu i zsumowanie wszystkich elementów wyrażenia wycenianego w tablicy w jednym wierszu/bez tworzenia zmiennych czasowych? Coś takiego jak sum(A-2*A,'-all')?

Edit: differes to z How can I index a MATLAB array returned by a function without first assigning it to a local variable?, gdyż nie dotyczy ogólnie (ani specyficzne) indeksowanie tablicy wyceniane wyrazu lub zwrotu wartości, ale raczej podsumowanie nad każdym możliwym indeksu.

Choć możliwe jest rozwiązanie mojego problemu z odpowiedzią podaną w linku, gnovice mówi, że używanie subref jest raczej brzydkim rozwiązaniem. Dalej Andras Deak zamieścił o wiele czystszy sposób robienia tego w komentarzach poniżej.

+1

Dlaczego tak bardzo chcesz uniknąć zmiennej tymczasowej? Nie ma to większego znaczenia z punktu widzenia szybkości, a także żadnego z punktu widzenia pamięci RAM (ta sama zmienna byłaby mimo wszystko tworzona w wywołaniu "sum"). Powiedziałbym, że 'suma (sum()) może być szybsza, ponieważ przekształcenie dużych macierzy zajmuje dużo czasu. – Adriaan

+1

@Daniel Wierzę, że istnieje prosta odpowiedź na to pytanie, która nie dotyczy duplikatu: 'sum (reshape (A-2 * A, 1, []))'. Ponownie otwórz, jeśli się zgodzisz, abym mógł odpowiedzieć. –

+0

@AndrasDeak Obie wersje działają, ale twoja wygląda o wiele czystsza niż przy użyciu 'subref'. Czy warto w tym przypadku ponownie otworzyć pytanie? (Nie mam pewności co do właściwego kodeksu postępowania tutaj.) –

Odpowiedz

10

Podczas gdy odpowiedzi na the linked duplicate mogą być rzeczywiście zastosowane do twojego problemu, węższy zakres twojego pytania pozwala nam dać znacznie prostsze rozwiązanie niż odpowiedzi tam dostarczone.

można podsumować wszystkie elementy w wyrażeniu (w tym wartość zwracana funkcji) przez przekształcanie swoją tablicę pierwszy 1d:

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

Będzie to przekształcić swój wyraz tablicy wartościami wielkości [1, N] gdzie N jest wywiedziony z rozmiaru tablicy, tj. numel(A-2*A) (ale powyższa składnia reshape wyliczy dla ciebie brakujący wymiar, bez potrzeby dwukrotnego oceniania twojego wyrażenia). Następnie jedno połączenie do sum zsumuje wszystkie elementy, w razie potrzeby.

Rzeczywisty przypadek gdzie masz uciekać się do czegoś, jak to jest, gdy funkcja zwraca tablicę z nieznanej liczbie wymiarów, i chcesz użyć jej sumę w anonimowej funkcji (making tymczasowy zmienne niedostępne):

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