Barry D.
Barry D.

Reputation: 547

How to check if a property from an object in a List<T> exists in another List<T>?

Friendly Notice: I am aware of the nested foreach method, but I'm trying to avoid it if there is a more efficient way.

Setup of Class 1:

public class Product{

      public int ID {get; set;}
      //Other irrelevant properties
}

Setup of Class 2:

public class JoinedDiscounts{

      public int ID {get; set;}
      public List<Product> Products = new List<Product>();
      //Other irrelevant properties

}

Suppose I now have a list of products (I've filtered specific products out into this list):

List<Product> products;

I also have this list.

List<JoinedDiscount> joinedDiscounts;

My goal is to check if any of the Joined Discounts from the joinedDiscounts list have a list of Products wherein any Product from the products list exists.

I think I've spent too much time thinking about it and now I'm having difficulty figuring out something that's probably very simple.

Any help is much appreciated

Upvotes: 0

Views: 549

Answers (4)

David
David

Reputation: 218798

Let's start from the top down...

if any of the Joined Discounts

Ok, so the outer structure is:

joinedDiscounts.Any()

But we need a boolean clause in there...

have a list of Products wherein any

Ok, we want to examine the .Products property and know if anything in that list matches a condition:

joinedDiscounts.Any(jd => jd.Products.Any())

Now we need a boolean clause in there...

any Product from the products list exists

So, if the products contains any given product of this collection?

joinedDiscounts.Any(jd => jd.Products.Any(p => products.Contains(p)))

That ought to do it, at least semantically.

However, if the comparator for Product isn't defined on that class then the code might just do a reference comparison, which might not be what you want. (Two instances may have the same values and may conceptually represent the same product, but they wouldn't be the same instance of the Product class.) If you need to drill further into the ID to manually compare, you'd have to do something like this:

joinedDiscounts.Any(jd => jd.Products.Any(prod => products.Select(p => p.ID).Contains(prod.ID)))

As the code grows, I'd recommend encapsulating comparison logic into your models appropriately. Implementing .Equals() and .GetHashCode() should do the trick in this case. That way consuming code stays simple and the logic is encapsulated on the objects where it belongs. That would allow you to perform semantically intuitive comparisons of your objects instead of drilling in to ID values manually.

Upvotes: 3

Steven Ackley
Steven Ackley

Reputation: 593

joinedDiscounts.Where(joinedDiscountse => joinedDiscountse.Products.Any()).ToList()

Upvotes: 0

johnny 5
johnny 5

Reputation: 20987

Using linq you can do this

List<JoinedDiscount> joinedDiscounts; //the joined products
List<Product> products; //desired products


joinedDiscounts.Where(d => d.Products.Any(
                     p => products.Select(prod => prod.ID).Contains(p.ID)
                     ).ToList()

Upvotes: 0

Glorin Oakenfoot
Glorin Oakenfoot

Reputation: 2623

This should give you an enumeration of the JoinedDiscounts in joinedDiscounts that contain a Product in products.

joinedDiscounts.Where(disc => disc.Products.Any(prod => products.Contains(prod)))

I think that covers what you're looking for.

Upvotes: 2

Related Questions