Saadi
Saadi

Reputation: 2237

Linq filter List base on List of object property

I trying to filter data using Linq. But I don't know where I'm doing wrong.

Here is the scenario:

I've two classes:

public class Category
{
    public int Id { get; set; }
    public bool Status { get; set; }
    public List<Product> Products { get; set; }
}

public class Product
{
    public int Id { get; set; }
    public bool Status { get; set; }
}

Here is how, I'm populating the categories list:

var categories = new List<Category>();
for (int i = 1; i <= 5; i++)
{
    var category = new Category
    {
        Id = i,
        Status = true
    };
    categories.Add(category);
}

foreach (var category in categories)
{
    var products = new List<Product>();
    for (int i = 1; i <= 5; i++)
    {
        var product = new Product
        {
            Id = i,
            Status = (i % 2 == 0)
        };
         products.Add(product);
     }
     category.Products = products;
 }

and I'm trying to get categories having product as status = true.

var filter = categories.Where(c => c.Products.Any(p => p.Status)).ToList();

but it's showing all of the products even the false one too.

I only want those products in the respective catalogs that are having status = true

output should be like this:

category1-> product2, product4
category2 -> product2, product4
category3 -> product2, product4
category4 -> product2, product4
category5 -> product2, product4

Upvotes: 1

Views: 4133

Answers (4)

Hossein Narimani Rad
Hossein Narimani Rad

Reputation: 32521

You can try this to get categories with those products that their status is true

var newCategories = categories.Select(
                        i => new Category { 
                                 Id = i.Id, 
                                 Status = i.Status, 
                                 Products = i.Products.Where(p => p.Status).ToList() 
                                 })
                              .ToList();

EDIT If you add a constructor for your Category class like this:

 public class Category
 {
     public int Id { get; set; }
     public bool Status { get; set; }
     public List<Product> Products { get; set; }

     public Category(int id, bool status)
     {
         this.Id = id;

         this.Status = status;
      }
 }

Then you do this (slightly better code than previous one)

var newCategories = categories.Select(
                        i => new Category(i.Id, i.Status) { 
                                 Products = i.Products.Where(p => p.Status).ToList() 
                                 })
                              .ToList();

Upvotes: 5

CHS
CHS

Reputation: 138

You're showing all the categories, which carry at least one Product == true. Therefore every product which has a true sibling in the same category will be listed.

This is also because you are basically not querying products but categories.

You could go:

var products = categories.SelectMany(c => c.Products).Where(p => p.Status).ToList();

Upvotes: 3

J88
J88

Reputation: 831

You're showing all the categories with one or more products with status true. That's why you get all of them because every category has at least a product with status true.

Upvotes: 1

Josh Knack
Josh Knack

Reputation: 405

In your code, you're adding products this way:

for (int i = 1; i <= 5; i++)
{
    var product = new Product
    {
       Id = i,
       Status = (i % 2 == 0)
    };
    products.Add(product);
 }

You will have 5 products in each category, 2 of which will have a status of true. You are selecting all categories that have at least one status == true product, which is every category.

Upvotes: 2

Related Questions