Hi! Ich studiere grade Wikipedia - Linq: LINQ
Alles ok, ausser was da zu Group steht. Dieses meine Testklasse:
public class Employee {
public string Name; public int Department; public int Age;
}
Und wenn ich nun den Wiki-Code bei mir einkopiere, kompiliert das nicht:
public void Test() {
var Employees = new List<Employee>();
var groupedEmployees =
from e in Employees
group e by e.Department
group e by e.Age
select e;
var groupedEmployees2 =
from e in Employees
group e by new { e.Department , e.Age }
select e;
Oder hab ich iwas falsch übernommen von denen?
In meinen Versuchen scheint beim Groupen ein into
-Abschnitt obligatorisch.
Und die 2-dimensionale Gruppierung (groupedEmployees
) bekomme ich ühaupt nicht gebacken 🙁
(naja - kaum hingeschrieben finde ich doch was):
var groupedEmployees =
from e in Employees
group e by e.Department into x
from y in x group y by y.Age into z
select z;
Edit: (und getestet, und es ist Blödsinn)
Der frühe Apfel fängt den Wurm.
Ja, der Artikel scheint fehlerhaft..
ich habe glaube auch noch nie ein group by ohne into gesehen. (Obwohl ich die ()=> schreibweise bevorzuge)
also dein 2. Beispiel müsste dann so aussehen:
from e in Employees
group e by new { e.Age,e.Department} into f
select f
Das erste geht imho so überhaupt nicht, weil das e nach dem group schon "out of scope" ist, und in f ist schon die fertige Gruppe. Darin könnte man nur noch soetwas wie
var groupedEmployees =
(from e in Employees
group e by new { e.Age,e.Department} into f
group f by f.Count() into g
select g).ToList();
machen.
Gruß
Wunderschönes Beispiel, wieso Wikipedia...egal, anderes Thema.
Ich komme mit der ausgeschriebenen Syntax nicht gut klar, aber der erste sollte so was hier sein:
var groupedEmployees = employees.GroupBy(p => p.Department, p => p, (p, d) => d.GroupBy(q => q.Age));
var groupedEmployees2 = employees.GroupBy(p => new { p.Age, p.Department });
Wenn ich richtig verstanden habe, was der WP-Autor uns sagen wollte. Wobei das zweite Beispiel viel mehr Sinn ergibt, wenn man das hier draus macht:
var groupedEmployees2 = employees.GroupBy(p => new { p.Age, p.Department }, p => p.Name);
Aber selbst dann ist das Beispiel ein ziemlich schlechtes.
LaTino
EDIT: erstes GroupBy-Beispiel durch andere Überladung von GroupBy-Extension ersetzt
EDIT: mglw. schwierig nachzuvollziehen, daher:
var groupedEmployees = employees
.GroupBy(
p => p.Department, //erstes Argument, anhand welcher Dimension aggregiert werden soll.
p => p, //transformation der Elemente bei der Auswahl, hier: keine
(p, d) => d.GroupBy(q => q.Age) //Anweisung nach dem Gruppieren, hier: innerhalb der Gruppe nochmals gruppieren, diesmal nach Alter.
);
Hoffe, das hilft ein wenig.
"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)
(Obwohl ich die ()=> schreibweise bevorzuge) Jo, dem neige ich jetzt auch zu, wenn ich so Vergleiche ziehe:
{
var result2 = from p in products group p by p.CategoryId into g select g;
var result3 = products.GroupBy(p => p.CategoryId);
}
Die Linq-Syntax hat 11 Wort-Zwischenräume (also textuelle Einheiten zu beachten), die Lambda-Schreibe nur 2 - oder mw. 4, wenn man Klammern auch als Text-Trenner auffasst.
Aber ich glaub ich werd in Zukunft eh kaum mehr groupen, denn grad habich .ToLookup entdeckt:
{ // ToLookup() als Alternative zum GroupBy: Ein Lookup ist gleichzeitig auch ein Dictionary der Groups
var result = products.ToLookup(p => p.CategoryId);
var x = result[4];
var result2 = from p in products group p by p.CategoryId into g select g;
var result3 = products.GroupBy(p => p.CategoryId);
var arr = result.ToArray();
arr = result2.ToArray();
arr = result3.ToArray();
}
syntax-Identisch mit GroupBy(), und auch die Ergebnismenge ist dieselbe (sieht man daran, dass aller dreier Datentyp nach ToArray an dieselbe variable zugewiesen werden kann.
Ein Lookup ist aber zusätzlich gleichzeitig auch sowas wie ein Dictionary, wo man die Groups also nicht nur enumerieren kann, sondern auch per Key zugreifen.
Ein Unterschied besteht ausserdem darin, dass Lookup bereits evaluiert ist - ist mir meist sogar erwünscht.
Jo das Wiki nicht wirklich eine Coder-Resource ist, sah und seh ich auch so. Aber die anderen Beschreibungen
(v.a. Join, Group Join, Left Outer Join, inkl DefaultIfEmpty
) fand ich sehr gut und auch bestätigt. Das hat mich denken machen, die wüssten, wovon sie reden 😉
Der frühe Apfel fängt den Wurm.
Zukunft eh kaum mehr groupen, denn grad habich .ToLookup entdeckt:
[..]
Ein Unterschied besteht ausserdem darin, dass Lookup bereits evaluiert ist - ist mir meist sogar erwünscht.
Zweischneidiges Schwert 😃. Die Nicht-Evaluierung hat einige Vorteile, weil bei Verkettungen der Gesamtausdruck optimiert ausgewertet wird/werden kann. Je nach Linq-Provider kann das sehr viel schneller und besser sein als das, was man per Hand erreicht, wenn man direkt auf den Daten arbeitet. Debuggen ist schwieriger, meiner Meinung nach. Dafür erzwingt das Arbeiten auf nicht-evaluierten Daten das Arbeiten MIT den Daten statt AUF* ihnen, was eine Umgewöhnung ist, aber das Leben leichter machen kann.
LaTino
var daten = datenbasis.Where(p => p.Eigenschaft == 5).ToList();
var result = new List<DatenEintrag>();
for(int i = 0; i < daten.Count; i++) //arbeiten AUF den Daten.
{
result.Add(new DatenEintrag(daten[i]));
}
var result2 = datenbasis.Where(p => p.Eigenschaft == 5).Select(p => new DatenEintrag(p)); //...und MIT den Daten. Noch wurde hier kein einziges Objekt erstellt.
"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)
Jo, da kann man einiges zu sagen, wann was günstiger ist.
Bei mir ist häufiger vor-evaluierung angezeigt, weil ich meine Listen leicht überwiegend mehrfach benutze.
Aber ist eh zu 99% irrelevant, denn nur ganz ganz selten habich mit Datenmengen von auch nur über 100 Stück zu tun - das wäre nichtmal schlimm, es mehrfach zu evaluieren.
Der frühe Apfel fängt den Wurm.