I have a list of instances of my own class "Vertrag" ("Contract") and need to group on them.
A simple GroupBy does exactly what I need: Group by the last four fields, the result is an IEnumerable<IGrouping<...,Vertrag>>. I can work with this result type, it is easy enough to iterate on.
At the spot marked ... is nothing given as type definition. So this seems to be an anonymous type?
Now I got a further request: Make sure that there is a max. three elements in each group. Start new groups (still same key!) until all are allocated. I found a solution to that as well in StackOverflow, the LINQ is a bit more complex but working fine. Just the return type is somewhat more complex.
I'd prefer to transform this complex structure back into the simple IGrouping-form so it works with the already existing code.
I got it almost working, or at least simplified down to a version that is as easy to use as the simple GroupBy one, yet not exactly the same. Is there a way to create this IGrouping with anonymous type yourself so that there is no need to change the code following the original grouping?
The key would come up identical more than once, exactly opposite of what GroupBy means to do. So I am not sure if a hand-crafted IGrouping would even allow that to exist.
This is a working LINQPad example (with type definition):
void Main()
{
List<Vertrag> verträge = new List<Vertrag>();
verträge.Add(new Vertrag("a1","b1","c","d","e"));
verträge.Add(new Vertrag("a2","b1","c","d","e"));
verträge.Add(new Vertrag("a3","b1","c","d","e"));
verträge.Add(new Vertrag("a4","b1","c","d","e"));
verträge.Add(new Vertrag("a5","b1","c","d","e"));
verträge.Add(new Vertrag("a6","b1","c","d","e"));
verträge.Add(new Vertrag("a7","b1","c","d","e"));
verträge.Add(new Vertrag("a1","b2","c","d","e"));
verträge.Add(new Vertrag("a2","b2","c","d","e"));
verträge.Add(new Vertrag("a3","b2","c","d","e"));
verträge.Add(new Vertrag("a4","b2","c","d","e"));
// Very easy first group
var verträgeGruppiert = verträge
.GroupBy(v => new { v.Beginn, v.Ende, v.Vorlage, v.Ware });
verträgeGruppiert.Dump();
// Far more complex grouping
var maxInGroup = 3;
var verträgeGruppiertMax = verträge
.GroupBy(v => new {v.Beginn, v.Ende, v.Vorlage, v.Ware})
.Select(g => new
{
Key = g.Key,
Teile = g.Select((v,i) => new {Value = v, Index = i})
.GroupBy(item => item.Index / maxInGroup)
});
verträgeGruppiertMax.Dump();
// Transform back into simpler style
// SelectMany used instead select, see comment in question
var vereinfacht = verträgeGruppiertMax
.SelectMany(vgm => vgm.Teile
.Select(t => new
{
vgm.Key,
a = t.Select(x => x.Value.ID)
}));
vereinfacht.Dump();
}
public class Vertrag
{
public Vertrag( // Constructor
string id,
string beginn,
string ende,
string vorlage,
string ware)
{
ID = id;
Beginn = beginn;
Ende = ende;
Vorlage = vorlage;
Ware = ware;
}
// Fields
public string ID { get; private set; }
public string Beginn { get; private set; }
public string Ende { get; private set; }
public string Vorlage { get; private set; }
public string Ware { get; private set; }
}