My goal is to group and transform data, but have both the transformed and un-transformed "grouped data" available.
Consider the following minimal C# example:
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))
};
Now I try to do the same in VB.NET, but I can only achieve that with a two-step process, because VB.NET's Group By
works somewhat differently than C#'s 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))
The problem seems to be that VB.NET's Group By
puts the result of the grouping into some kind of "global namespace": If I continue writing LINQ code directly after Group d By d.Item1 Into Group
, I have both Item1
and Group
in scope. However, I don't have a name for the IGrouping
consisting of them (dubbed g
in C#), so I need the second step.
Can I somehow tell VB's Group By
statement to give me a name for the IGrouping
? The only other workarounds I found were to use (a) functional syntax instead of declarative LINQ syntax (i.e., call Enumerable.GroupBy
directly) or (b) nest step1 into the second step (i.e., From g In (...step1...)
). Is there something I have missed?
CodePudding user response:
It's too bad that the C# and VB LINQ syntax is so incompatible. I think the following VB LINQ is as close as you can get the to the original (with Option Infer On of course):
Dim data = { ("a", 1), ("a", 2), ("b", 1) }
Dim groupedAndTransformed = From d In data
Group d By d.Item1 Into g = Group
Select New With {
Key .Untransformed = g,
Key .Transformed = Item1 & String.Join(",", g.Select(Function(tuple) tuple.Item2))
}
I've tested and it compiles and runs but it's hard to tell if it will function identically.
CodePudding user response:
What Dave said, but I just wanted to note that overall it might be neater to use method syntax:
Dim groupedAndTransformed = data.GroupBy(
Function(d) d.Item1,
Function(k, g) New With {
Key .Untransformed = g
Key .Transformed = g.Select(Function(tuple) tuple.Item2)
}
)
Or if you want to dump the Untransformed, there's an overload that will help reduce the subselect
Dim groupedAndTransformed = data.GroupBy(
Function(d) d.Item1,
Function(d) d.Item2,
Function(k, g) New With {
Key .Transformed = k & String.Join(",", g)
}
)
I do wish they'd shorten Function
to F