This question is similar to LINQ group one type of item but handled in a more generic way.
I have a List that has various derived classes. I may have something like this:
List<BaseClass> list = new List<BaseClass>() {
new Class1(1),
new Class2(1),
new Class1(2),
new Class3(1),
new Class2(2),
new Class4(1),
new Class3(2)
};
I am trying to use LINQ to semi-sort the list so that the natural order is maintained EXCEPT for certain classes which have base.GroupThisType == true. All classes with GroupThisType should be grouped together at the place that the first class of the same type occurs. Here is what the output should be like:
List<BaseClass> list = new List<BaseClass>() {
new Class1(1),
new Class1(2),
new Class2(1),
new Class3(1),
new Class3(2)
new Class2(2),
new Class4(1),
};
Edit: Oops, forgot to say this result is assuming (Class1 and Class3).GroupThisType == true
Like this:
list = list.Select((o, i) => new { Index = i * 10000, Value = o })
.GroupBy(q => q.GetType())
.SelectMany(g => {
if (g.First().GroupThisType)
return g.Select((q, i) =>
new { Index = g.First().Index + i, Value = q.Value }
);
else
return g;
})
.OrderBy(q => q.Index)
.Select(q => q.Value)
.ToList();
The i * 10000
allows up to 10,000 items from a group to be inserted between any two items.
You can replace g.First().GroupThisType
with typesToGroup.Contains(g.Key)
.
Here's a solution using two passes: in the first I build a dictionary of all the ones that should group. In the second I use SelectMany to gather up the elements that don't collate with the collated sequences for the first of any element that does collate.
// Build a dictionary of the items that group
var onesToGroup = list.Where(x => x.GroupThisClass)
.GroupBy(x => x.GetType())
.ToDictionary(x => x.Key, x => x.AsEnumerable());
var results = list.SelectMany(x => x.GroupThisClass ?
(onesToGroup[x.GetType()].First() == x ? onesToGroup[x.GetType()] : (new BaseClass[]{}))
: (new []{x}));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With