#c# #linq
Вопрос:
Примечание: У меня нет дерева с отношением «родитель и потомок», вместо этого я пытаюсь сгруппировать аналогичный код и сохранить его вместе и сформировать вложенные объекты/коллекцию
У меня есть сценарий, в котором мои данные выровнены и я хотел бы сформировать вложенную коллекцию на основе кода и хранилища.
public class Item
{
public int Code { get; set; }
public string Price { get; set; }
public int Store { get; set; }
public string PriceType { get; set; }
}
public class PriceDto
{
public string PriceType { get; set; }
public string Price { get; set; }
}
public class ItemVm
{
public int Code { get; set; }
public int Store { get; set; }
public List<PriceDto> SalePrice { get; set; }
public List<PriceDto> PermPrice { get; set; }
}
public static class IEnumerableExtension
{
public static IEnumerable<TSource> DistinctBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
HashSet<TKey> seenKeys = new HashSet<TKey>();
foreach (TSource element in source)
{
if (seenKeys.Add(keySelector(element)))
{
yield return element;
}
}
}
}
У меня ниже приведен код для формирования вложенной коллекции из сплющенного списка.
IList<Item> items = new List<Item>() {
new Item() { Code = 1, Price = "3.83", Store = 1202, PriceType = "Sale"} ,
new Item() { Code = 1, Price = "4.10", Store = 1202, PriceType = "Perm"} ,
new Item() { Code = 2, Price = "3.00", Store = 1315, PriceType = "Perm"} ,
new Item() { Code = 3, Price = "1.99" , Store = 1420, PriceType = "Sale"} ,
new Item() { Code = 3, Price = "2.25" , Store = 1420, PriceType = "Perm" }
};
//Distinct Code, Store amp; then form nested collection by loop
var itemsList = items.Select(
i => new ItemVm { Code = i.Code, Store = i.Store, }
).DistinctBy(d => new { d.Code,d.Store }).ToList();
foreach( var i in itemsList)
{
i.PermPrice = items.Where(x=> x.Code == i.Code amp;amp; x.Store == i.Store amp;amp; x.PriceType == "Perm").Select(d => new PriceDto
{ Price = d.Price, PriceType = d.PriceType }).ToList();
i.SalePrice = items.Where(x=> x.Code == i.Code amp;amp; x.Store == i.Store amp;amp; x.PriceType == "Sale").Select(d => new PriceDto
{ Price = d.Price, PriceType = d.PriceType }).ToList();
}
Есть ли лучший способ, чем этот, сформировать вложенную коллекцию в одном запросе LINQ ?
Любые предложения.
Комментарии:
1. Звучит как
GroupBy
2. @Ivan Steoev как бы это работало с GroupBy, так как group by получит только первую строку или только ключевые значения в группе, а не другие значения, такие как PermPrice и SalePrice, которые я получил с помощью цикла foreach
3. Хм, из мира SQL? LINQ
GroupBy
отличается — смотрите здесь и здесь
Ответ №1:
Вы должны использовать GroupBy
var itemsList = items
.GroupBy(d => new { d.Code, d.Store })
.Select(g => new ItemVm
{
Code = g.Key.Code,
Store = g.Key.Store,
PermPrice = g.Where(x => x.PriceType == "Perm")
.Select(d => new PriceDto { Price = d.Price, PriceType = d.PriceType })
.ToList(),
SalePrice = g.Where(x => x.PriceType == "Sale")
.Select(d => new PriceDto { Price = d.Price, PriceType = d.PriceType })
.ToList()
})
.ToList();