选择其字段间差异最小的项目

时间:2012-08-20 12:17:20

标签: c# lambda

我有一个项目列表。 我必须选择两个属性之间差异最小的项目。

例如:学生{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;

我可以在一个声明中实现吗?这样做的性能是什么? 这将是乐观的

4 个答案:

答案 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);