2015-12-01 13 views
5

So habe ich mich schon seit einiger Zeit darüber gewundert. Fasst man über einige Array-Variable A ist so einfach wieMATLAB Summe über alle Elemente der Array-Wert Ausdruck

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

jedoch, sobald es die (:) funktioniert nicht mehr, wie

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

auf Ausdrücke erhält keine gültige Matlab-Syntax, sondern müssen wir schreiben

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 

die obige Motto wird nur funktionieren, wenn die Dimension von A festgelegt ist, die, je nachdem, was man tut, kann nicht erforderlich sei der Fall. Der Nachteil der beiden Zeilen ist, dass foo so lange im Speicher bleibt, bis Sie clear foo ausführen oder je nach Größe von A und was sonst noch in Ihrem Arbeitsbereich ist, gar nicht möglich ist.

Gibt es eine allgemeine Möglichkeit, dieses Problem zu umgehen und alle Elemente eines array-bewerteten Ausdrucks in einer einzigen Zeile zusammenzufassen/ohne temporäre Variablen zu erstellen? Etwas wie sum(A-2*A,'-all')?

bearbeiten: Es differiert die von How can I index a MATLAB array returned by a function without first assigning it to a local variable?, da es sich nicht um allgemeine tut (noch spezifisch) Indizierung von Array bewertet Ausdrücke oder Werte zurückgeben, sondern die Summe über jeden möglichen Index.

Während es möglich ist, mein Problem mit der Antwort zu lösen, die in der Verbindung gegeben wird, sagt gnovice selbst, dass subref eine ziemlich hässliche Lösung ist. Weiter hat Andras Deak in den folgenden Kommentaren einen viel saubereren Weg eingeschlagen.

+1

Warum sind Sie so eifrig auf die temporäre Variable zu vermeiden? Es spielt keine Rolle in Bezug auf die Geschwindigkeit und auch nicht hinsichtlich des Arbeitsspeichers (die gleiche Variable würde sowieso im Aufruf 'Summe' erzeugt). Ich würde sagen, 'sum (sum())' könnte schneller sein, da das Umformen großer Matrizen viel Zeit in Anspruch nimmt. – Adriaan

+1

@Daniel Ich glaube, es gibt eine einfache Antwort auf diese Frage, die das Duplikat nicht betrifft: 'sum (Umformen (A-2 * A, 1, []))'. Bitte öffnen Sie erneut, wenn Sie einverstanden sind, damit ich antworten kann. –

+0

@AndrasDeak Beide Versionen funktionieren, aber Ihre sieht viel sauberer dann mit 'subref'. Lohnt es sich, in diesem Fall eine Frage erneut zu stellen? (Ich bin mir nicht sicher über den richtigen Verhaltenskodex hier.) –

Antwort

10

Während die Antworten auf the linked duplicate in der Tat auf Ihr Problem angewendet werden können, ermöglicht der engere Umfang Ihrer Frage uns, eine viel einfachere Lösung als die dort angegebenen Antworten zu geben.

Sie können alle Elemente in einem Ausdruck Summe (einschließlich der Rückgabewert einer Funktion) von Array ersten bis 1d Umformung:

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

Dies wird neu gestalten Sie Ihre Array-wertigen Ausdruck Größe [1, N] wo N wird aus der Größe des Arrays abgeleitet, dh numel(A-2*A) (aber die obige Syntax von reshape berechnet die fehlende Dimension für Sie, keine Notwendigkeit, Ihren Ausdruck zweimal auszuwerten). Dann wird ein einzelner Aufruf an sum alle Elemente nach Bedarf summieren.

Der eigentliche Fall, in dem Sie haben so zu etwas greifen ist, wenn eine Funktion ein Array mit einer unbekannten Anzahl von Dimensionen zurückgibt, und Sie ihre Summe in einer anonymen Funktion verwenden möchten (was temporäre Variablen nicht verfügbar):

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