I have a simple List that I would like to display, grouped by which Category it is a member of. All the examples I have seen use GroupBy but with a single ID, I'm having trouble figuring out how to do so with a List. It's ok if the product appears under both Categories.
public class Product
{
public int Id { get; set; }
public string Title { get; set; }
public List<Category> Categories { get; set; }
}
StringBuilder ProductList = new StringBuilder();
var p = _products.GroupBy(a => a.Categories);
foreach (var item in p)
{
ProductList.Append($"<p><strong>{item.Key}</strong><br/>");
foreach (var e in item)
{
ProductList.Append($"{e.Title}");
ProductList.Append("</p>");
}
}
CodePudding user response:
Here's a solution with sample data you can test yourself:
var categories = Enumerable.Range(0, 10).Select(n => new Category { Id = n }).ToArray();
var products = new[]
{
new Product { Id = 1, Title = "P1", Categories = new List<Category> { categories[0], categories[1], categories[2] } },
new Product { Id = 2, Title = "P2", Categories = new List<Category> { categories[0], categories[1], categories[3] } },
new Product { Id = 3, Title = "P3", Categories = new List<Category> { categories[0], categories[2], categories[3] } },
new Product { Id = 4, Title = "P4", Categories = new List<Category> { categories[0], categories[2], categories[3] } },
new Product { Id = 5, Title = "P5", Categories = new List<Category> { categories[0], categories[3], categories[5] } },
new Product { Id = 6, Title = "P6", Categories = new List<Category> { categories[0], categories[4], categories[5] } },
};
var categoryGroups =
from p in products
from c in p.Categories
group p by c.Id into g
select g;
foreach (var categoryGroup in categoryGroups)
{
Console.WriteLine($"Category {categoryGroup.Key}:");
foreach (var product in categoryGroup)
{
Console.WriteLine($"\tProduct {product.Id}: {product.Title}");
}
Console.WriteLine("-----------------------------------------------------");
}
I assume class Category
has some id property, e.g. Id
, to group by. If it's reference based grouping you can replace group p by c.Id into g
with group p by c into g
.
CodePudding user response:
You can use SelectMany
to flatten the list into tuples of (Product, Category)
, then use GroupBy
to group product by category.
StringBuilder ProductList = new StringBuilder();
var p = _products
.SelectMany(a => a.Categories, (prod, cat) => (prod, cat))
.GroupBy(tuple => tuple.cat, tuple => tuple.prod);
foreach (var item in p)
{
ProductList.Append($"<p><strong>{item.Key}</strong><br/>");
foreach (var e in item)
{
ProductList.Append(e.Title);
ProductList.Append("</p>");
}
}