Let's say we have a List<Product>
and each product item in the list has many List<Type>
public class Product{
public int Id {get:set;}
public string Name {get:set;}
public List<Type> Types {get;set;}
}
public class Type{
public int Id {get;set;}
public string Name{get;set;}
}
After I create a product list, I need to group them by the type and then find all the belongs to each type. I think I should try LINQ
for this. Here is what I have done so far, but seems not the right way to get the job done. May be someone can help me.
var productsList = new List<Product>();
//Adding products and types for each of them
var productTypesList = new Dictionary<int, string>();
foreach (var p in productsList)
{
var pTypes = p.Types;
foreach (var ptype in
pTypes.Where(x=> !productTypesList .ContainsKey(x.Id)))
{
productTypesList.Add(ptype.Id, ptype.Name);
}
}
Then I'm trying to search Like this
foreach (var t in productTypesList)
{
var matches = productsList.FindAll(........);
// from here I need to find all the product which belongs to type (t.id)
if (matches.Count > 0)
{
//Do somthing here
}
}
The following does what you want:
var productsPerType =
from t in products.SelectMany(
p => p.Types, (p, t) => new { Product = p, TypeId = t.Id })
group t by t.TypeId
into g
select new { g.Key, Products = g.Select(x => x.Product) };
First, you do a SelectMany
to get a list of all types inside the products. For each type you remember the type id and the corresponding product:
from t in products.SelectMany(
p => p.Types, (p, t) => new { Product = p, TypeId = t.Id })
Each t
is now an anonymous object containing a type id and a product. Next, you group these objects by type id. Now we have a group of products for each type id.
To give you an example, suppose you have the following products and types:
Product A -- Types 1, 2, 3
Product B -- Types 1
Product C -- Types 1, 3
The SelectMany
gives the following intermediate result:
1, A
2, A
3, A
1, B
1, C
3, C
We group this result by type id so we get the following groups:
1, { A, B, C }
2, { A }
3, { A, C }
And this is the result you wanted.
var types = (from p in productsList
from t in p.Types
select t).Distinct(new TypeComparerById());
var productsGrouped = (from t in types
select new
{
Type = t,
ProductsPerType = productsList.Where(p=>p.Types.Any(pt=>pt.Id == t.Id))
}).ToList();
Edit
Ronald Wildenberg has correctly pointed that the call on Distinct() would work only if the instances are the same. To correct this I update with the following implementation
public class TypeComparerById : IEqualityComparer<Type>
{
public bool Equals(Type t1, Type t2)
{
if (t1.Id == t2.Id)
{
return true;
}
else
{
return false;
}
}
public int GetHashCode(Type t)
{
return t.Id.GetHashCode();
}
}
You should pick his answer as being the correct one (although the next one is correct too)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With