Das mag lahm klingen, aber ich habe noch keine wirklich gute Erklärung gefunden für Aggregate
.
Gut bedeutet kurz, beschreibend, umfassend und mit einem kleinen, klaren Beispiel.
Das mag lahm klingen, aber ich habe noch keine wirklich gute Erklärung gefunden für Aggregate
.
Gut bedeutet kurz, beschreibend, umfassend und mit einem kleinen, klaren Beispiel.
Die am einfachsten zu verstehende Definition von Aggregate
besteht darin, dass es an jedem Element der Liste eine Operation durchführt und dabei die vorangegangenen Operationen berücksichtigt. Das heißt, sie führt die Operation am ersten und zweiten Element durch und trägt das Ergebnis weiter. Dann führt es die Operation am vorherigen Ergebnis und am dritten Element durch und trägt das Ergebnis weiter. usw.
Beispiel 1. Summieren von Zahlen
var nums = new[]{1,2,3,4};
var sum = nums.Aggregate( (a,b) => a + b);
Console.WriteLine(sum); // output: 10 (1+2+3+4)
Dies fügt hinzu 1
y 2
zu machen 3
. Dann fügt er hinzu 3
(Ergebnis der vorherigen) und 3
(nächstes Element in der Reihenfolge) zu machen 6
. Dann fügt er hinzu 6
y 4
zu machen 10
.
Beispiel 2. Erstellen einer csv-Datei aus einem Array von Strings
var chars = new []{"a","b","c", "d"};
var csv = chars.Aggregate( (a,b) => a + ',' + b);
Console.WriteLine(csv); // Output a,b,c,d
Dies funktioniert auf ähnliche Weise. Verketten a
ein Komma und b
zu machen a,b
. Dann verkettet a,b
mit einem Komma und c
zu machen a,b,c
. und so weiter.
Beispiel 3. Multiplikation von Zahlen mit einem Seed
Der Vollständigkeit halber sei erwähnt, dass es eine Überlastung de Aggregate
die einen Startwert annimmt.
var multipliers = new []{10,20,30,40};
var multiplied = multipliers.Aggregate(5, (a,b) => a * b);
Console.WriteLine(multiplied); //Output 1200000 ((((5*10)*20)*30)*40)
Ähnlich wie in den obigen Beispielen beginnt dies mit einem Wert von 5
und multipliziert es mit dem ersten Element der Folge 10
mit einem Ergebnis von 50
. Dieses Ergebnis wird vorgetragen und mit der nächsten Zahl in der Folge multipliziert 20
zu einem Ergebnis von 1000
. Dies setzt sich für die restlichen 2 Elemente der Sequenz fort.
Live-Beispiele: http://rextester.com/ZXZ64749
Dokumente: http://msdn.microsoft.com/en-us/library/bb548651.aspx
Nachtrag
Im obigen Beispiel 2 wird die Verkettung von Zeichenfolgen verwendet, um eine Liste von Werten zu erstellen, die durch ein Komma getrennt sind. Dies ist eine vereinfachte Art, die Verwendung von Aggregate
was die Absicht dieser Antwort war. Wenn diese Technik jedoch verwendet wird, um eine große Menge an kommagetrennten Daten zu erstellen, wäre es sinnvoller, eine StringBuilder
und dies ist durchaus vereinbar mit Aggregate
unter Verwendung der gesetzten Überlast zur Auslösung der StringBuilder
.
var chars = new []{"a","b","c", "d"};
var csv = chars.Aggregate(new StringBuilder(), (a,b) => {
if(a.Length>0)
a.Append(",");
a.Append(b);
return a;
});
Console.WriteLine(csv);
Aktualisiertes Beispiel: http://rextester.com/YZCVXV6464
Es hängt zum Teil davon ab, von welcher Überlastung man spricht, aber die Grundidee ist die gleiche:
(currentValue, sequenceValue)
in (nextValue)
currentValue = nextValue
currentValue
Vielleicht finden Sie die Aggregate
Beitrag in meiner Edulinq-Serie nützlich - sie enthält eine ausführlichere Beschreibung (einschließlich der verschiedenen Überladungen) und Implementierungen.
Ein einfaches Beispiel ist die Verwendung von Aggregate
als Alternative zu Count
:
// 0 is the seed, and for each item, we effectively increment the current value.
// In this case we can ignore "item" itself.
int count = sequence.Aggregate(0, (current, item) => current + 1);
Oder vielleicht die Summierung aller Längen von Zeichenketten in einer Folge von Zeichenketten:
int total = sequence.Aggregate(0, (current, item) => current + item.Length);
Ich persönlich selten めっけもの Aggregate
nützlich - die "maßgeschneiderten" Aggregationsmethoden sind für mich in der Regel gut genug.
Super kurz Aggregate funktioniert wie fold in Haskell/ML/F#.
Geringfügig länger .Max(), .Min(), .Sum(), .Average() iteriert über die Elemente einer Sequenz und aggregiert sie mit der jeweiligen Aggregatfunktion. .Aggregate () ist ein verallgemeinerter Aggregator, der es dem Entwickler erlaubt, den Startzustand (auch Seed genannt) und die Aggregatfunktion anzugeben.
Ich weiß, dass Sie um eine kurze Erklärung gebeten haben, aber ich dachte mir, da andere ein paar kurze Antworten gegeben haben, dass Sie vielleicht an einer etwas längeren Erklärung interessiert wären
Langfassung mit Code Eine Möglichkeit zur Veranschaulichung könnte sein, zu zeigen, wie Sie die Probe Standardabweichung einmal mit foreach und einmal mit .Aggregate. Hinweis: Ich habe die Leistung hier nicht priorisiert, so dass ich die Sammlung unnötigerweise mehrmals wiederhole.
Zunächst eine Hilfsfunktion zur Erstellung einer Summe quadratischer Abstände:
static double SumOfQuadraticDistance (double average, int value, double state)
{
var diff = (value - average);
return state + diff * diff;
}
Dann Stichprobe Standardabweichung mit ForEach:
static double SampleStandardDeviation_ForEach (
this IEnumerable<int> ints)
{
var length = ints.Count ();
if (length < 2)
{
return 0.0;
}
const double seed = 0.0;
var average = ints.Average ();
var state = seed;
foreach (var value in ints)
{
state = SumOfQuadraticDistance (average, value, state);
}
var sumOfQuadraticDistance = state;
return Math.Sqrt (sumOfQuadraticDistance / (length - 1));
}
Dann einmal mit .Aggregate:
static double SampleStandardDeviation_Aggregate (
this IEnumerable<int> ints)
{
var length = ints.Count ();
if (length < 2)
{
return 0.0;
}
const double seed = 0.0;
var average = ints.Average ();
var sumOfQuadraticDistance = ints
.Aggregate (
seed,
(state, value) => SumOfQuadraticDistance (average, value, state)
);
return Math.Sqrt (sumOfQuadraticDistance / (length - 1));
}
Beachten Sie, dass diese Funktionen bis auf die Art und Weise, wie sumOfQuadraticDistance berechnet wird, identisch sind:
var state = seed;
foreach (var value in ints)
{
state = SumOfQuadraticDistance (average, value, state);
}
var sumOfQuadraticDistance = state;
Versus:
var sumOfQuadraticDistance = ints
.Aggregate (
seed,
(state, value) => SumOfQuadraticDistance (average, value, state)
);
Aggregate kapselt also dieses Aggregator-Muster und ich erwarte, dass die Implementierung von Aggregate in etwa so aussehen wird:
public static TAggregate Aggregate<TAggregate, TValue> (
this IEnumerable<TValue> values,
TAggregate seed,
Func<TAggregate, TValue, TAggregate> aggregator
)
{
var state = seed;
foreach (var value in values)
{
state = aggregator (state, value);
}
return state;
}
Die Verwendung der Standardabweichungsfunktionen würde etwa so aussehen:
var ints = new[] {3, 1, 4, 1, 5, 9, 2, 6, 5, 4};
var average = ints.Average ();
var sampleStandardDeviation = ints.SampleStandardDeviation_Aggregate ();
var sampleStandardDeviation2 = ints.SampleStandardDeviation_ForEach ();
Console.WriteLine (average);
Console.WriteLine (sampleStandardDeviation);
Console.WriteLine (sampleStandardDeviation2);
IMHO
Hilft .Aggregate also der Lesbarkeit? Im Allgemeinen liebe ich LINQ, weil ich denke, dass .Where, .Select, .OrderBy und so weiter die Lesbarkeit erheblich verbessern (wenn man inlined hierarhische .Selects vermeidet). Aggregate müssen aus Gründen der Vollständigkeit in Linq enthalten sein, aber ich persönlich bin nicht davon überzeugt, dass .Aggregate die Lesbarkeit im Vergleich zu einem gut geschriebenen foreach verbessert.
Zur Erinnerung:
Func<X, Y, R>
ist eine Funktion mit zwei Eingängen des TypsX
yY
die ein Ergebnis vom TypR
.
Enumerable.Aggregate hat drei Überladungen:
Überlastung 1:
A Aggregate<A>(IEnumerable<A> a, Func<A, A, A> f)
Exemple :
new[]{1,2,3,4}.Aggregate((x, y) => x + y); // 10
Diese Überlastung ist einfach, hat aber die folgenden Einschränkungen:
InvalidOperationException
.Überlastung 2:
B Aggregate<A, B>(IEnumerable<A> a, B bIn, Func<B, A, B> f)
Exemple :
var hayStack = new[] {"straw", "needle", "straw", "straw", "needle"};
var nNeedles = hayStack.Aggregate(0, (n, e) => e == "needle" ? n+1 : n); // 2
Diese Überlastung ist eher allgemeiner Natur:
bIn
).Überlastung 3:
C Aggregate<A,B,C>(IEnumerable<A> a, B bIn, Func<B,A,B> f, Func<B,C> f2)
Die dritte Überlast ist IMO nicht sehr nützlich.
Das Gleiche lässt sich knapper formulieren, indem man die Überladung 2 verwendet, gefolgt von einer Funktion, die ihr Ergebnis umwandelt.
Die Illustrationen sind angepasst von dieser ausgezeichnete Blogpost .
Das Aggregat wird grundsätzlich zur Gruppierung oder Zusammenfassung von Daten verwendet.
A "Aggregate Function Wendet eine Akkumulatorfunktion auf eine Sequenz an."
Beispiel 1: Addiere alle Zahlen in einer Reihe.
int[] numbers = new int[] { 1,2,3,4,5 };
int aggregatedValue = numbers.Aggregate((total, nextValue) => total + nextValue);
*Wichtig: Der anfängliche Aggregatwert ist standardmäßig das 1 Element in der Auflistungsfolge. D.h.: der Anfangswert der Gesamtvariablen ist standardmäßig 1.
variable Erklärung
total: enthält den von der Funktion zurückgegebenen Summenwert (aggregierter Wert).
nextValue: Es handelt sich um den nächsten Wert in der Array-Sequenz. Dieser Wert wird dann zu dem aggregierten Wert, d.h. der Gesamtsumme, addiert.
Beispiel 2: Hinzufügen aller Elemente in einem Array. Legen Sie auch den anfänglichen Akkumulatorwert fest, um mit der Addition von 10 zu beginnen.
int[] numbers = new int[] { 1,2,3,4,5 };
int aggregatedValue = numbers.Aggregate(10, (total, nextValue) => total + nextValue);
Argumente erklären:
das erste Argument ist der Initialwert (Startwert, d.h. Seed-Wert), der verwendet wird, um die Addition mit dem nächsten Wert im Array zu beginnen.
das zweite Argument ist eine func, die 2 int benötigt.
1.total: Hier wird wie zuvor der von der Funktion nach der Berechnung zurückgegebene Summenwert (aggregierter Wert) gespeichert.
2.nextValue: : Es handelt sich um den nächsten Wert in der Array-Sequenz. Dieser Wert wird dann zu dem aggregierten Wert, d.h. der Gesamtsumme, addiert.
Auch das Debuggen dieses Codes wird Ihnen ein besseres Verständnis für die Funktionsweise von Aggregaten vermitteln.
CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.