Simplify regular nested foreach loops using linq & lambda expression

(see my code snippet below). I want to find all coll1 elements that match coll2 elements (number of coll2 elements <= number of coll1 elements) and put the query result in coll3. How to achieve this with linq expression and lambda? Of course, I can just copy coll2 to coll3 :-), but that is not my goal. I want to know how to use linq and lambda to replace such a conditional logical construct. Thank you in advance.

var coll1 = new List<int>() { 1, 2, 3, 4, 5 }; var coll2 = new List<int>() { 2, 4 }; var coll3 = new List<int>(); foreach ( var selected in coll2 ) { foreach ( var item in coll1 ) { if ( selected == item ) { coll3.Add(item); } } } 
+4
source share
6 answers

You can use Intersect

 coll1.Intersect(coll2); 

But this will not work as expected (see commentary of the king of the king). You can do it instead

 coll2.Where(x=>coll1.Any(y=>x==y)); 
+14
source
 coll3 = coll1.Where(i => coll2.Contains(i)).ToList(); 

Update. A bit simpler as suggested in the comments:

 coll3 = coll1.Where(coll2.Contains).ToList(); 
+6
source

As a first step, you can use where to make your code more readable:

  var coll1 = new List<int>() { 1, 2, 3, 4, 5 }; var coll2 = new List<int>() { 2, 4 }; var coll3 = new List<int>(); foreach (var selected in coll2) { coll3.AddRange(coll1.Where(item => selected == item)); } 
+2
source

Use Intersect: http://msdn.microsoft.com/en-us/library/bb460136.aspx

 var coll3 = coll1.Intersect(coll2) 
+2
source

You can do it; not sure if this is more readable tho!

 var coll3 = (from selected in coll2 from item in coll1 where selected == item select item).ToList(); 
+1
source

If you do not want to directly assign the result to your list, you can add 'ForEach' to your Linq statement:

 coll1.Where(i => coll2.Contains(i)).ToList().ForEach(i => coll3.Add(i)); 

You might want to check out Distinct, though

0
source

Source: https://habr.com/ru/post/1493622/


All Articles