Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Select items from a List where the children contain the items from another List using LINQ

Tags:

c#

linq

I have the following classes:

Product:

public class Product
{
    public string Name { get; set; }
    public List<Category> Categories { get; set; }
}

And Category:

public class Category
{
    public string Id { get; set; }
    public string Name { get; set; }
}

And I have the following method:

public List<Product> FilterProducts(List<Category> categories)
{
    // filtering code here
}

Question: How can I filter my products using a List<Categories> as parameter?

EDIT: One thing I forgot to mention is that if I have 2 categories I should be able to see only the products with the category1 AND category2. What I've done so far has returned only products with category1 OR category2. Although inherit IEquatable use Intersect seems interesting I am comparing with the Id's for now.

like image 641
Davidson Sousa Avatar asked Dec 15 '22 08:12

Davidson Sousa


1 Answers

If you want to return all the products which has all the provided categories in its Categories which means it selects product where it has category1 AND category2.

Then you need to use the All with the combination of Contains:

public List<Product> FilterProducts(List<Category> categories)
{
    return products.Where(p => categories.All(c => p.Categories.Contains(c))
                   .ToList();
}

If you want to return all the product where it has it least one cetegory from the provided categories which means it selects product where it has category1 OR category2.

Then you need to use Any

public List<Product> FilterProducts(List<Category> categories)
{
    return products.Where(p => categories.Any(c => p.Categories.Contains(c)
                   .ToList();
}

Please not that if your categories objects are not the same instances which you have in the Categories property of the product or in your Category you are not overriding the Equals method to use the Id you may want to compare the Ids instead of the category objects themselves.

So something like:

The solution with all

public List<Product> FilterProducts(List<Category> categories)
{
     return products.Where(p => categories
        .All(c => p.Categories.Any(cat => cat.Id == c.Id)).ToList()
}

The solution with any

public List<Product> FilterProducts(List<Category> categories)
{
    return products.Where(p => categories
        .Any(cat => p.Categories.Any(pcat => pcat.Id == cat.Id)).ToList();
}
like image 84
nemesv Avatar answered Jan 30 '23 09:01

nemesv