我有一个项目列表。 我必须选择两个属性之间差异最小的项目。
例如:学生{string Name,int ScoredMarks,int TotalMarks} 注意:所有学生的总分数不一样。 我必须选择与TotalMarks和ScoredMarks差异最小的学生。 我能够这样做
int minDiff = students.Min(x => (x.TotalMarks - x.ScoredMarks));
var result = from s in students
where s.TotalMarks - s.ScoredMarks == minDiff
select s;
我可以在一个声明中实现吗?这样做的性能是什么? 这将是乐观的
答案 0 :(得分:4)
您可以使用Math.Abs
获取绝对差异,按顺序排序并取第一个。
Student minDiff = students
.OrderBy(x => Math.Abs(x.TotalMarks - x.ScoredMarks))
.FirstOrDefault();
if(minDiff != null)
{
// ...
}
如果您想获得最佳效果,请使用MinBy
的Skeets MoreLinq。我的方法需要在获取具有最小差异的值之前按值排序所有项目。
如果我必须选择所有差异最小的学生,即如果我有多个学生的最小差异相同,那该怎么办。
然后你可以使用GroupBy
:
var minDiffGroup = students
.GroupBy(x => Math.Abs(x.TotalMarks - x.ScoredMarks))
.OrderBy(g => g.Key)
.FirstOrDefault();
foreach(Student student in minDiffGroup)
{
// ...
}
答案 1 :(得分:0)
试试这个:
Student TheOne = StudentList.OrderBy<Student, int>(x => x.TotalMarks - x.ScoredMarks).First<Student>();
答案 2 :(得分:0)
我认为你可以将两者结合起来。
var result = from s in students
where s.TotalMarks - s.ScoredMarks == students.Min(x => (x.TotalMarks - x.ScoredMarks))
select s;
但需要注意的是,这取决于您所查询的内容,这决定了这是一个“更好”的解决方案。如果它是linq-to-objects,那么每次都会运行.Min(...),这是一个更糟糕的表现。如果是实体框架,则将整个lambda转换为SQL,这是一种更好的性能。
答案 3 :(得分:0)
MoreLinq具有MinBy和MaxBy功能:
为了进一步简化这一点,我建议在学生对象中添加一个属性
public int PriorTotalMarks { get { return this.TotalMarks - this.ScoredMarks; } }
附加属性可以绑定到数据网格,聚合等等。没有混合的额外复杂性。
然后,使用Jon Skeet的MinBy,您只需写下:
Students.MinBy(s => s.PriorTotalMarks);