Используйте LINQ для подсчета количества комбинаций в двух списках - PullRequest
1 голос
/ 18 июня 2010

Я пытаюсь создать запрос (или запросы) LINQ, который подсчитывает общее количество совпадений элементов в одном списке, которые существуют в другом списке. Например, возьмите следующие списки:

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

Результат операции запроса должен быть равен 2, поскольку я могу найти две комбинации AAA и BBB (из DiscountItems) в содержимом CartItems.

Я подумываю подойти к запросу, чтобы объединить списки, чтобы сократить CartItems и включить только элементы из DiscountItems. Решение состоит в том, чтобы найти CartItem в результирующем запросе, который встречается наименьшее количество раз, что указывает, сколько комбинаций элементов существует в CartItems.

Когда CartItems фильтруется только для элементов в DiscountItems, это может визуально отображаться так:

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

Таким образом, поскольку в корзине 2 комбинации скидок, результат равен 2.

Как это можно сделать?


Вот запрос, который у меня уже есть, но он не работает. query приводит к перечислению из 100 элементов, намного больше, чем я ожидал.

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

Ответы [ 2 ]

3 голосов
/ 18 июня 2010

Я думаю, что вы хотите, это размер набора пересечение на основе вашего описания.

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

Это предполагает, что предметы на самом деле одинаковы (и они сопоставимы). Если нет, то вам нужно выбрать только те ключи, которые вы используете для их сравнения, и выполнить пересечение ключей.

 return Cart.CartItems.Select( Function(c) c.SKU )
                      .Intersect( DiscountGroup.DiscountItems
                                               .Select( Function(d) d.SKU  )
                      .Count()
2 голосов
/ 18 июня 2010

Если я правильно понимаю ваш вопрос, вы хотите:

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

Результат:

2

Предполагается, что DiscountItems не может содержать дубликаты. Если это возможно, и вы хотите, чтобы дубликат означал, что товар должен появиться в корзине дважды, чтобы считаться одной скидкой, тогда используйте вместо этого код:

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

Я только что заметил, что вы хотели получить ответ в VB.NET. Я полагаю, что вам легче перевести это на VB.NET, чем мне, поскольку мой VB.NET не так уж и хорош, но если нет, то оставьте сообщение, и я попытаюсь запустить его через .NET Reflector, чтобы посмотреть, сможет ли переведите его автоматически на что-то читаемое.

...