Linq query to get common items in a sublist

I have a class that has a property that is List, I will call this class A. Then I have List<A> .

I need LINQ for objects in order to get all objects B that are present in ALL elements in List<A> .

Example for clarification:

 var list = new List<A> { new A { B = new List<B> { B1, B2, B3, B4 } } new A { B = new List<B> { B3, B4, B5, B6 } } new A { B = new List<B> { B2, B3, B4, B5, B6 } } }; 

The query should return B3 and B4 objects, since they are the only ones contained in all List<A> objects.

+7
source share
4 answers

If you have a list of lists and you want the items to be in all internal lists, you can use a combination of Aggregate and Intersect , for example:

 IEnumerable<IEnumerable<string>> listOfLists = new string[][] { new string[] { "B1", "B2", "B3", "B4" }, new string[] { "B3", "B4", "B5", "B6" }, new string[] { "B2", "B3", "B4", "B5", "B6" } }; IEnumerable<string> commonElements = listOfLists.Aggregate(Enumerable.Intersect); 
+10
source

You can simply use Intersect() if there is at least one element, and your class B has an adequate equality implementation / GetHashCode() :

 IEnumerable<B> allBs = list[0].B; foreach (var item in list.Skip(1)) { allBs = allBs.Intersect(item.B); } 

I do not see the benefits of a β€œclean” Linq solution other than adding complexity.

+4
source

While Equals / GetHashCode is correctly defined for objects of type B, this is actually somewhat simple:

 _listToQuery.Aggregate( _listToQuery.First().B, (seed, nextItem) => { seed = seed.Intersect(nextItem.B); return seed; }) 

Or else:

 _listToQuery.SelectMany(tr => tr.B) .GroupBy(tr => tr) .Where(tr => tr.Count() == _listToQuery.Count) .Select(tr => tr.Key) 
+2
source

The way I approach this is to create a list of all Bs and then figure out which ones happen more than once, grouping them with some unique identifier (or just an object if they are comparable). When they are grouped, select those where the number of copies is greater than 1, using the first instance of each group as the canonical representative.

 var selection = list.SelectMany( a => aB ) .GroupBy( b => b.UniqueID, b => b ) .Where( b => b.Count() > 1 ) .Select( b => b.First() ); 
+2
source

All Articles