#c# #linq
#c# #linq
Вопрос:
У меня есть приложение-календарь, в котором вы выбираете различные комбинации продуктов — служба выходит и получает доступные даты на основе диапазона дат календаря. Дата является «доступной» только в том случае, если ВСЕ выбранные продукты доступны на определенную дату.
class SelectedProduct
{
public int ID { get; set; }
public int Qty { get; set; }
}
class AvailableInventory
{
public int ID { get; set; }
public DateTime Date { get; set; }
}
// List of selected products from user
List<SelectedProduct> SelectedProducts;
// populated from service with all dates for all products
List<AvailableInventory> AvailableInventory;
Я хочу иметь возможность сказать, получить список доступных запасов для каждой даты, который содержит запасы для всех идентификаторов в выбранных продуктах.
Это (нерабочий) код pusdo возможного решения, я просто недостаточно хорошо знаю linq, чтобы сделать это правильно
var results = List<AvailableInventory>();
foreach (var group in AvailableInventory.GroupBy(x => x.Date))
{
if (group.Contains(ALL ID's in SelectedProducts)
{
results.AddRange(group);
}
}
Комментарии:
1. Хорошо, что ты уже пробовал? Вы должны продемонстрировать свои усилия, а не просто просить нас написать код для вас.
2. слово хаха- я могу выполнить вышеописанное с помощью очень уродливого цикла — искал более элегантное решение LINQ — опубликую одну секунду.
3. является ли ваша
Date
собственность вAvailableInventory
int
илиDate
?4. Дата и время, извините, будут изменены.
5. хорошо, отправил ответ.
Ответ №1:
Это группирует запасы по дате (игнорируя часть даты), затем выбирает только те группы, которые содержат все выбранные идентификаторы продуктов, и, наконец, выбирает все доступные запасы для соответствующих групп.
var results =
AvailableInventory.GroupBy(i => i.Date.Date)
.Where(g => !SelectedProducts.Select(p => p.ID)
.Except(g.Select(i => i.ID))
.Any())
.SelectMany(g => g);
Результатом является коллекция AvailableInventory
.
Ответ №2:
Вы можете сгруппировать по дате, а затем отфильтровать группы, в которых нет всех выбранных продуктов.
// List of selected products from user
List<SelectedProduct> SelectedProducts = new List<SelectedProduct> {
new SelectedProduct { ID = 1, Qty = 1 },
new SelectedProduct { ID = 2, Qty = 2 },
};
// populated from service with all dates for all products
List<AvailableInventory> AvailableInventory = new List<AvailableInventory> {
new AvailableInventory { ID = 1, Date = new DateTime(2014, 04, 11) },
new AvailableInventory { ID = 2, Date = new DateTime(2014, 04, 11) },
new AvailableInventory { ID = 1, Date = new DateTime(2014, 04, 12) },
new AvailableInventory { ID = 2, Date = new DateTime(2014, 04, 13) },
new AvailableInventory { ID = 1, Date = new DateTime(2014, 04, 14) },
new AvailableInventory { ID = 2, Date = new DateTime(2014, 04, 14) },
};
var query = AvailableInventory.GroupBy(i => i.Date)
.Where(g => SelectedProducts.All(s => g.Any(i => i.ID == s.ID)));
foreach(var group in query)
{
Console.WriteLine("Date: {0}", group.Key);
foreach(var inventory in group)
{
Console.WriteLine(" Available: {0}", inventory.ID);
}
}
Это привело бы к:
Date: 4/11/2014 12:00:00 AM
Available: 1
Available: 2
Date: 4/14/2014 12:00:00 AM
Available: 1
Available: 2
Ответ №3:
Я думаю, это то, что вы ищете. Попробуйте это
var result = AvailableInventory.Where(i => SelectedProducts.Any(x => x.ID == i.ID)).GroupBy(o => o.Date)
.Select(g => g.First()).ToList();
Это тестовые данные, которые я использовал на основе вашего определения класса для AvailableInventory
и SelectedProduct
// List of selected products from user
List<SelectedProduct> SelectedProducts = new List<SelectedProduct> {
new SelectedProduct { ID = 1, Qty = 2 },
new SelectedProduct { ID = 2, Qty = 4 },
new SelectedProduct { ID = 5, Qty = 10 }
};
// populated from service with all dates for all products
List<AvailableInventory> AvailableInventory = new List<AvailableInventory> {
new AvailableInventory { ID = 1, Date = new DateTime(2014, 04, 01) },
new AvailableInventory { ID = 2, Date = new DateTime(2014, 04, 02) },
new AvailableInventory { ID = 3, Date = new DateTime(2014, 04, 02) },
new AvailableInventory { ID = 4, Date = new DateTime(2014, 04, 10) },
new AvailableInventory { ID = 5, Date = new DateTime(2014, 04, 10) }
};
Это должно дать вам только записи с ID = 1, ID = 2 and ID = 5
, потому что это то, что является общим для обоих AvailableInventory
и SelectedProducts
списков.
Ответ №4:
Это помогло бы, если бы вы действительно попробовали что-нибудь.
Учитывая это:
List<SelectedProduct> SelectedProducts ;
List<AvailableInventory> AvailableInventory ;
Что-то вроде этого, вероятно, даст то, что вы хотите:
int[] DatesWithAllSelectedProductsAvailable =
AvailableInventory
.GroupBy( x => x.Date )
.Where ( g => g.All( x => SelectedProducts.Any( p => p.ID == x.ID ) ) )
.Select( x => x.Key )
.Distinct()
.OrderBy( x => x )
.ToArray()
;
Комментарии:
1. Поверьте мне, я пытался… свистящий звук, который раздался у меня над головой, был на одном уровне с 747.