I have a list of my objects:
class MyObj
{
public String Title { get; set; }
public Decimal Price { get; set; }
public String OtherData { get; set; }
}
var list = new List<MyObj> {
new MyObj { Title = "AAA", Price = 20, OtherData = "Z1" },
new MyObj { Title = "BBB", Price = 20, OtherData = "Z2" },
new MyObj { Title开发者_如何转开发 = "AAA", Price = 30, OtherData = "Z5" },
new MyObj { Title = "BBB", Price = 10, OtherData = "Z10" },
new MyObj { Title = "CCC", Price = 99, OtherData = "ZZ" }
};
What is the best way to get list with unique Title and MAX(Price). Resulting list needs to be:
var ret = new List<MyObj> {
new MyObj { Title = "BBB", Price = 20, OtherData = "Z2" },
new MyObj { Title = "AAA", Price = 30, OtherData = "Z5" },
new MyObj { Title = "CCC", Price = 99, OtherData = "ZZ" }
};
Well, you could do:
var query = list.GroupBy(x => x.Title)
.Select(group =>
{
decimal maxPrice = group.Max(x => x.Price);
return group.Where(x => x.Price == maxPrice)
.First();
};
If you need LINQ to SQL (where you can't use statement lambdas) you could use:
var query = list.GroupBy(x => x.Title)
.Select(group => group.Where(x => x.Price == group.Max(y => y.Price))
.First());
Note that in LINQ to Objects that would be less efficient as in each iteration of Where
, it would recompute the maximum price.
Adjust the .First()
part if you want to be able return more than one item with a given name if they both have the same price.
Within LINQ to Objects you could also use MoreLINQ's MaxBy
method:
var query = list.GroupBy(x => x.Title)
.Select(group => group.MaxBy(x => x.Price));
var ret = list.GroupBy(x => x.Title)
.Select(g => g.Aggregate((a, x) => (x.Price > a.Price) ? x : a));
(And if you need the results to be a List<T>
rather than an IEnumerable<T>
sequence then just tag a ToList
call onto the end.)
var ret = list.OrderByDescending(x => x.Price).GroupBy(x => x.Title).Select(@group => @group.ElementAt(0)).ToList();
this should do it.
Would like to mention that
var query = list.GroupBy(x => x.Title)
.Select(group => group.Where(x => x.Price == group.Max(y => y.Price))
.First());
Should be
var query = list.GroupBy(x => x.Title)
.First(group => group.Where(x => x.Price == group.Max(y => y.Price)));
I like the Richard solution to greatest-n-per-group problem.
var query = list
.OrderByDescending(o => o.Price) //set ordering
.GroupBy(o => o.Title) //set group by
.Select(o => o.First()); //take the max element
However it needs to be slightly modified
var query = list
.OrderByDescending(o => o.Price) //set ordering
.GroupBy(o => o.Title) //set group by
.Select(o => o.Where(k => k.Price == o.First().Price)) //take max elements
精彩评论