Omri
Omri

Reputation: 1078

C#- Select specific items from a list based on partial intersection with another list (Linq + Lambda)

I have two lists:

List<objA> list1
List<objB> list2

class objA
{
   string Name;
}

class objB
{
   string Name;
   bool SomeProp;
}

Using C# linq/lambda I want to select all the objA objects which has their Name property equals to the name property of the second obj (list1.Name == list2.Name) and check another property of objB (list2.SomeProp == true).

Upvotes: 3

Views: 878

Answers (2)

Sergey Berezovskiy
Sergey Berezovskiy

Reputation: 236218

I recommend to use join:

from a in list1
join b in list2 on a.Name equals b.Name
where b.SomeProp
select a

Lambda syntax:

list1.Join(listb.Where(b => b.SomeProp),
           a => a.Name, b => b.Name, (a,b) => a)

NOTE: Thus you will avoid enumerating list2 collection for each item in list1 (solution with Any)


To show difference between two solutions - lets see what they look like after translating linq to plain loops. First is

list1.Where(a => list2.Any(b => b.Name == a.Name && b.SomeProp))

It is equivalent to

foreach(var a in list1)
{
   foreach(var b in list2)
   {
       if (a.Name == b.Name && b.SomeProp)
       {
           yield return a;
           break;
       }
   }
} 

As you can see - it has nested loop, and complexity is O(N*M). With join we have Lookup created for inner sequence:

Lookup<string, objB> lookup = list2.Where(b => b.SomeProp).ToLookup(b => b.Name);

foreach(var a in list1)
{
    Grouping<string, objB> g = lookup.GetGrouping(a.Name);
    if (g == null)
       continue;

    foreach(var b in g)
       yield return a;
}

Difference here is searching in lookup - which is O(1) operation. Total complexity will be O(M +N)

Upvotes: 7

Selman Gen&#231;
Selman Gen&#231;

Reputation: 101681

This should do it:

list1.Where(a => list2.Any(b => b.Name == a.Name && b.SomeProp));

Upvotes: 4

Related Questions