I’m building an auction site and the user can bid on the same item more than once (obviously). In the user’s dashboard, a user can view his bids. When the user bids on the same item more than once, I want only one entry with the highest bid value to show up. My current code shows an entry for each bid. I tried a few things but I couldn’t figure it out. Here’s what I’ve got:
public class Bid
{
public int Id { get; set; }
public double Amount { get; set; }
public DateTime Date { get; set; }
public virtual Item Item { get; set; }
public virtual User User { get; set; }
}
protected override List<ItemForUserBids> ResolveCore(User source)
{
var items = new List<ItemForUserBids>();
var userBids = source.Bids;
foreach (var bid in userBids)
{
var item = bid.Item;
var c = new ItemForUserBids
{
BidValue = bid.Amount,
BidId = bid.Id,
Description = item.Description,
Id = item.Id,
ItemThumb = item.MainImageLink(),
Status = _itemsService.GetBiddingStatus(item, source),
TimeLeft = item.EndDate.TimeLeft(),
Title = item.Title
};
items.Add(c);
}
return items;
}
I tried to get Distinct bids based on the Item.Id but that did not work. Now I’m thinking maybe I could use the Date property of the Bid entity somehow to get to the result I want but my head stopped thinking.
Any suggestions?
UPDATE:
I got it to work using a dictionary and using OrderBy() and Max() like many suggested. But I think the latter could be further improved.
Implementation using a dictionary (works):
var userBids = new Dictionary<string, Bid>();
foreach (var bid in allUserBids)
{
var key = bid.Item.Id.ToString();
if(userBids.ContainsKey(key))
{
if (userBids[key].Amount < bid.Amount)
userBids[key] = bid;
}
userBids[key] = bid;
}
Attempt using the other method (works):
var highestBids =
source.Bids.Where(x => x.Date > DateTime.Now.AddYears(-1))
.GroupBy(x => x.Item.Id,
(itemId, bids) =>
new
{
ItemId = itemId,
MaxBid = bids.Max(x => x.Amount)
}).ToList();
var userBids = new List<Bid>();
foreach (var bid in source.Bids)
{
for(var i = 0; i < highestBids.Count; i++)
{
var curr = highestBids[i];
if (bid.Item.Id.Equals(curr.ItemId) && bid.Amount.Equals(curr.MaxBid)) {
userBids.Add(bid);
highestBids.Remove(curr);
}
}
}
How do I get rid of those loops? And maybe have it all in one chained statement?
The comments posted so far should be a good indication that you should look into re-architecting this a little, but the immediate code solution involves using System.Linq to chain together a GroupBy, Max, and a Select.