Mein Ziel ist es, Daten zu gruppieren und zu transformieren, aber sowohl die transformierten als auch die nicht transformierten "gruppierten Daten" verfügbar zu haben.
Betrachten Sie das folgende minimale C#-Beispiel:
var data = new[] { ("a", 1), ("a", 2), ("b", 1) };
var groupedAndTransformed =
from d in data
group d by d.Item1 into g
select new
{
Untransformed = g,
Transformed = g.Key + string.Join(",", g.Select(tuple => tuple.Item2))
};
Jetzt versuche ich dasselbe in VB.NET zu tun, aber ich kann das nur mit einem zweistufigen Prozess erreichen, weil VB.NET Group By
etwas anders funktioniert als C# group by
:
Dim data = {("a", 1), ("a", 2), ("b", 1)}
Dim step1 =
From d In data
Group d By d.Item1 Into Group
Dim groupedAndTransformed =
From g In step1
Select
Untransformed = g,
Transformed = g.Item1 + String.Join(",", g.Group.Select(Function(tuple) tuple.Item2))
Das Problem scheint zu sein, dass VB.NET Group By
das Ergebnis der Gruppierung in eine Art "globalen Namensraum" stellt: Wenn ich direkt nach weiter LINQ-Code schreibe Group d By d.Item1 Into Group
, habe ich beide Item1
und Group
im Gültigkeitsbereich. Allerdings habe ich keinen Namen für die IGrouping
aus ihnen bestehenden (synchronisiert g
in C#), also brauche ich den zweiten Schritt.
Kann ich der Anweisung von VB irgendwie sagen Group By
, dass sie mir einen Namen für das geben soll IGrouping
? Die einzigen anderen Problemumgehungen, die ich gefunden habe, waren die Verwendung (a) der funktionalen Syntax anstelle der deklarativen LINQ-Syntax (dh Enumerable.GroupBy
direkter Aufruf) oder (b) die Verschachtelung von step1 im zweiten Schritt (dh From g In (...step1...)
). Gibt es etwas, das ich verpasst habe?
Lösung des Problems
Im geposteten C#-Code ist die Variable g
vom Typ System.Linq.Lookup.Grouping. Dieser Typ ist eine interne Klasse vom Typ System.Linq.Lookup. Da die Absicht von LINQ zu sein scheint, die Lookup-Gruppierungen zu extrahieren, wäre es vielleicht besser, die Abfrage so zu schreiben, dass sie die Enumerable.ToLookup-Methode verwendet, um eine Aufzählung der Gruppierungen zu erstellen.
var groupedAndTransformed = from grp in data.ToLookup((item) => item.Item1)
select new
{
Untransformed = grp,
Transformed = grp.Key + string.Join(",", grp.Select((tuple) => tuple.Item2))
};
Dies kann direkt in VB-Code übersetzt werden.
Dim groupedAndTransformed = From grp In data.ToLookup(Function(item) item.Item1)
Select New With
{
Key.Untransformed = grp,
Key.Transformed = grp.Key & String.Join(",", grp.Select(Function(tuple) tuple.Item2))
}
Mir ist klar, dass dies nicht die Frage beantwortet, wie „Group By" von VB gezwungen werden kann, dieselbe interne Implementierung zu verwenden, die der C#-Compiler ausgibt, aber möchten Sie wirklich Code, der sich auf ein Implementierungsdetail stützt?
Keine Kommentare:
Kommentar veröffentlichen