2010-06-17 8 views
1

J'essaie de créer une ou plusieurs requêtes LINQ qui comptent le nombre total d'occurrences de combinaisons d'éléments dans une liste existant dans une liste différente. Par exemple, prenez les listes suivantes:Utilisez LINQ pour compter le nombre de combinaisons existant dans deux listes

CartItems     DiscountItems 
=========     ============= 
AAA      AAA 
AAA      BBB 
AAA 
BBB 
BBB 
CCC 
CCC 
DDD 

Le résultat de l'opération de requête doit être 2 puisque je peux trouver deux combinaisons de AAA et BBB (de DiscountItems) dans le contenu de CartItems.

Mon idée en approchant la requête est de joindre les listes ensemble pour raccourcir CartItems pour inclure uniquement les éléments de DiscountItems. La solution serait de trouver le CartItem dans la requête résultante qui se produit le moins de fois, indiquant ainsi combien de combinaisons d'éléments existent dans CartItems.

Lorsque CartItems est filtré uniquement les éléments DiscountItems, il peut être visuellement affiché comme ceci:

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 

Ainsi, parce qu'il ya 2 combinaisons de la remise dans le panier, le résultat est 2.

Comment cela peut-il être fait?


est ici la requête que je l'ai déjà, mais il ne fonctionne pas. query résultats dans une énumération avec 100 articles, beaucoup plus que ce à quoi je m'attendais.

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)) 
+0

Peut-être que simplement appeler Distinct couperait tous les multiples de matchs? –

+0

La liste DiscountItems peut également contenir des doublons. Si oui, qu'est-ce que cela signifie - doivent-ils être dans la liste originale deux fois? –

+1

Je pense qu'il y a une certaine confusion au sujet de ce que signifie votre question. Pour clarifier, pourriez-vous répondre à cette question ... si le panier = A, A, A et la remise = A, le résultat devrait-il être 1 ou 3? –

Répondre

2

Si je comprends bien votre question, vous voulez ceci:

int count = DiscountItems.Min(x => CartItems.Count(item => item == x)); 

Résultat:

2 

Cela suppose que DiscountItems ne peuvent pas contenir des doublons. Si elle peut et que vous souhaitez un duplicata signifie que l'élément doit apparaître dans le panier deux fois pour compter comme une réduction puis utilisez ce code à la place:

int count = DiscountItems 
    .GroupBy(d => d) 
    .Min(x => CartItems.Count(item => item == x.Key)/x.Count()); 

Je viens de remarquer que vous vouliez une réponse en VB.NET. J'imagine que vous êtes plus facilement capable de traduire cela en VB.NET que possible car mon VB.NET n'est pas génial, mais si ce n'est pas le cas, laissez un message et j'essaierai de le lancer via .NET Reflector pour voir s'il peut le traduire automatiquement en quelque chose de lisible.

+0

Merci pour la réponse. Je préfère généralement coder en C#, mais je dois utiliser VB.NET pour le travail. Je peux traduire cela quand je vais le tester. Une différence immédiate que j'ai remarquée entre C# et VB.NET quand il s'agit de LINQ est de savoir comment les lambda sont exprimés. Au lieu de '(item => item == x.Key)', vous avez '(fonction (item) (item = x.Key))'. –

3

Je pense que ce que vous voulez, c'est la taille de l'ensemble intersection basé sur votre description.

return Cart.CartItems.Intersect(DiscountGroup.DiscountItems).Count() 

Cela suppose que les éléments sont vraiment les mêmes (et ils sont comparables). Si ce n'est pas le cas, vous devez sélectionner uniquement les clés que vous utilisez pour les comparer et faire une intersection sur les touches.

return Cart.CartItems.Select(Function(c) c.SKU) 
         .Intersect(DiscountGroup.DiscountItems 
               .Select(Function(d) d.SKU ) 
         .Count() 
+0

Je n'ai peut-être pas été clair dans ma question originale et je l'ai depuis édité pour clarification. L'intersection montre en fait les éléments qui existent dans les deux ensembles, mais elle ne les montre * qu'une fois *. J'ai besoin du nombre de fois que tous les éléments de l'ensemble 'DiscountItems' apparaissent dans l'ensemble' CartItems'. –

+0

Donc, fondamentalement, ce que vous voulez est de compter le nombre de fois que vous pouvez supprimer le tuple représenté dans la liste de réduction des articles du panier? Je pense que la réponse de @ Mark fonctionnera pour cela puisque c'est fondamentalement le nombre minimum d'occurrences dans CartItems de chaque article dans les articles de réduction. – tvanfosson