我有一个简单的课:
class Balls
{
public int BallType;
}
我有一个非常简单的列表:
var balls = new List<Balls>()
{
new Balls() { BallType = 1},
new Balls() { BallType = 1},
new Balls() { BallType = 1},
new Balls() { BallType = 2}
};
我在此列表上使用过GroupBy
,我想找回拥有最高计数/金额的钥匙:
使用x.GroupBy(q => q.BallType)
之后,我尝试使用.Max()
,但是它返回3,我需要的密钥是1。
我也尝试使用Console.WriteLine(x.GroupBy(q => q.Balltype).Max().Key);
,但是它抛出了System.ArgumentException
。
答案 0 :(得分:1)
这是我想出的:
var mostCommonBallType = balls
.GroupBy(k => k.BallType)
.OrderBy(g => g.Count())
.Last().Key
您按BallType分组,按组中的项目数排序,获取最后一个值(因为order by按升序排列,最常见的值为最后一个),然后返回它的键值
答案 1 :(得分:1)
有人提出了对序列进行排序的想法:
var mostCommonBallType = balls
.GroupBy(k => k.BallType)
.OrderBy(g => g.Count())
.Last().Key
除此以外,OrderByDescending
并使用FirstOrDefault
效率更高,如果您的Balls集合为空,也会遇到麻烦。
如果您使用不同的GroupBy重载,则不会出现这些问题
var mostCommonBallType = balls.GroupBy(
// KeySelector:
k => k.BallType,
// ResultSelector:
(ballType, ballsWithThisBallType) => new
{
BallType = ballType,
Count = ballsWithThisBallType.Count(),
})
.OrderByDescending(group => group.Count)
.Select(group => group.BallType)
.FirstOrDefault();
这解决了前面提到的问题。但是,如果只需要第一个元素,为什么要订购第二个和第三个元素呢?使用Aggregate代替OrderByDescending将仅枚举一次:
假设您的收藏集不为空:
var result = ... GroupBy(...)
.Aggregate( (groupWithHighestBallCount, nextGroup) =>
(groupWithHighestBallCount.Count >= nextGroup.Count) ?
groupWithHighestBallCount : nextGroup)
.Select(...).FirstOrDefault();
Aggregate接受非空序列的第一个元素,并将其分配给groupWithHighestBallCount。然后遍历序列的其余部分,并将此nextGroup.Count与groupWithHighestBallCount.Count进行比较。它将具有最高值的一个作为下一个groupWithHighestBallCount。返回值是最终的groupWithHighestBallCount。
看到聚合只枚举一次吗?