Reputation: 33118
I'm trying to create a LINQ query (or queries) that count the total number of occurences of a combinations of items in one list that exist in a different list. For example, take the following lists:
CartItems DiscountItems
========= =============
AAA AAA
AAA BBB
AAA
BBB
BBB
CCC
CCC
DDD
The result of the query operation should be 2 since I can find two combinations of AAA
and BBB
(from DiscountItems
) within the contents of CartItems
.
My thinking in approaching the query is to join the lists together to shorten CartItems
to only include items from DiscountItems
. The solution would be to find the CartItem
in the resulting query that occurs the least amount of times, thus indicating how many combinations of items exist in CartItems
.
When CartItems
is filtered to only the items in DiscountItems
, it can be visually displayed like this:
CartItems that get a discount
=============================
AAA BBB <= This combination is eligible for a discount
AAA BBB <= This combination is eligible for a discount
AAA <= Not eligible
Thus, because there are 2 combinations of the discount in the Cart, the result is 2.
How can this be done?
Here's the query I already have, but it's not working. query
results in an enumeration with 100 items, far more than I expected.
Dim query = From cartItem In Cart.CartItems
Group Join discountItem
In DiscountGroup.DiscountItems
On cartItem.SKU Equals discountItem.SKU
Into Group
Select SKU = cartItem.SKU, CartItems = Group
Return query.Min(Function(x) x.CartItems.Sum(Function(y) y.Quantity))
Upvotes: 1
Views: 977
Reputation: 838944
If I understand your question correctly you want this:
int count = DiscountItems.Min(x => CartItems.Count(item => item == x));
Result:
2
This assumes that DiscountItems cannot contain duplicates. If it can and you want a duplicate to mean that the item must appear in the cart twice to count as one discount then use this code instead:
int count = DiscountItems
.GroupBy(d => d)
.Min(x => CartItems.Count(item => item == x.Key) / x.Count());
I just noticed that you wanted an answer in VB.NET. I imagine that you are more easily able to translate this to VB.NET than I can as my VB.NET is not so great, but if not then leave a message and I will try running it through .NET Reflector to see if it can translate it automatically to something readable.
Upvotes: 2
Reputation: 532615
I think what you want is the size of the set intersection based on your description.
return Cart.CartItems.Intersect( DiscountGroup.DiscountItems ).Count()
This assumes that the items are really the same things (and they are comparable). If not, then you'd need to select out just the keys that you use to compare them and do an intersection on the keys.
return Cart.CartItems.Select( Function(c) c.SKU )
.Intersect( DiscountGroup.DiscountItems
.Select( Function(d) d.SKU )
.Count()
Upvotes: 3