Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

LINQ - List Lowest Prices Only

Tags:

c#

linq

Consider this code:

var items = (new[] { 
    new {itemTypeId = 1 , cost=100 },
    new {itemTypeId = 2 , cost=200 },
    new {itemTypeId = 1 , cost=50 },
    new {itemTypeId = 3 , cost=150 },
    new {itemTypeId = 1 , cost=75 }
});

var o = items.OrderBy(x => x.cost)
    .ToList()
    .GroupBy(x => x.itemTypeId )
    .Select(g => new { g, count = g.Count() })
    .SelectMany(t => t.g.Select(b => b).Zip(Enumerable.Range(1, t.count), (j, i) => new { j.itemTypeId , j.cost }));

foreach (var i in o)
{
    Console.WriteLine("{0} {1} ", i.itemTypeId, i.cost);
}

Output:

1 | 50  
1 | 75  
1 | 100  
3 | 300  
2 | 200

I actually want it to output:

1 | 50   
2 | 200
3 | 300

The query should only return products of a certain type with the lowest price. So in any returned data there should only be one of each item type and ordered by price.

I thought Enumerable.Range(1, t.count) did a similar job as Row_number over in TSQL.Personally I can't see what on earth the above code actually achieves unless I've written it complete wrong.

Any suggestions?

like image 326
ComfortablyNumb Avatar asked Dec 11 '22 20:12

ComfortablyNumb


1 Answers

Group by the item type, which gives you an IGrouping<T>, from that you get a key and an IEnumerable<T> of grouped items. You can then project (Select) that into an anonymous type, using Min on the IGrouping<T> that is x to get the lowest cost per group:

items
    .GroupBy(x => x.itemTypeId)
    .Select(x => new { ItemTypeId = x.Key, Cost = x.Min(z => z.cost) })
    .OrderBy(x => x.Cost)
like image 73
haim770 Avatar answered Dec 23 '22 15:12

haim770