I run into this problem over and over again: how can I group a list of objects using a list of other objects?
I have a list of objects of type A , and each of these objects has a property (lets call it ListProp ), which is also a list. ListProp has type B elements. There are several type A elements with identical B objects in ListProp , but the ListProp property ListProp is different from element to element. How can I group these A objects in the fastest way, where the B objects in ListProp identical?
A
ListProp
B
Code example:
class Program { static void Main(string[] args) { var exampleList = new List<A> { // Should be in first group new A { ListProp = new List<B> { new B { Prop = new C { Number = 0 }}, new B { Prop = new C { Number = 1 }} }}, // Should be in first group new A { ListProp = new List<B> { new B { Prop = new C { Number = 0 }}, new B { Prop = new C { Number = 1 }} }}, // Should be in second group new A { ListProp = new List<B> { new B { Prop = new C { Number = 0 }}, new B { Prop = new C { Number = 1 }}, new B { Prop = new C { Number = 1 }} }}, // Should be in third group new A { ListProp = new List<B> { new B { Prop = new C { Number = 0 }}, new B { Prop = new C { Number = 0 }} }} }; // Doesn't work because the reference of ListProp is always different var groupedExampleList = exampleList.GroupBy(x => x.ListProp); } } class C { public int Number { get; set; } public override bool Equals(object o) { if (o is C) return Number.Equals(((C)o).Number); else return false; } } class B { public C Prop { get; set; } } class A { public IList<B> ListProp { get; set; } }
You can implement IEqualityComparer<List<B>> and use it in another GroupBy overload.
IEqualityComparer<List<B>>
public class ListOfBEqualityComparer : IEqualityComparer<List<B>> { public bool Equals(List<B> x, List<B> y) { // you can also implement IEqualityComparer<B> and use the overload return x.SequenceEqual(y); } public int GetHashCode(List<B> obj) { //implementation of List<T> may not work for your situation return obj.GetHashCode(); } }
Then you can use overload
var groupedExampleList = exampleList.GroupBy(x => x.ListProp, new ListOfBEqualityComparer());
Try the following:
GroupBy(x => String.Join(",", x.ListProp));
It will be grouped by 0,1; 0,1; 0,1; 0,1,1; 0,1 0,1; 0,1; 0,1; 0,1,1; 0,1 0,1; 0,1; 0,1; 0,1,1; 0,1 respectively.
0,1; 0,1; 0,1; 0,1,1; 0,1
I would approach this as follows:
var data = exampleList.SelectMany(a=>a.ListProp.Select(x=>new{Key = x.Prop.Number, Value = a})) .GroupBy(x=>x.Key) .Select(g=>new {Number = g.Key, Items = g.ToList()});