我有一个具有两个int属性的对象列表。该列表是另一个linq查询的输出。对象:

public class DimensionPair  
{
    public int Height { get; set; }
    public int Width { get; set; }
}

我想在列表中找到并返回具有最大Height属性值的对象。

我可以设法获得高度值的最大值,但不是对象本身。

我可以用Linq做这个吗?如何?


当前回答

我相信按你想要的列排序,然后抓取第一个应该是可行的。然而,如果有多个对象具有相同的MAX值,则只有一个对象会被抓取:

private void Test()
{
    test v1 = new test();
    v1.Id = 12;

    test v2 = new test();
    v2.Id = 12;

    test v3 = new test();
    v3.Id = 12;

    List<test> arr = new List<test>();
    arr.Add(v1);
    arr.Add(v2);
    arr.Add(v3);

    test max = arr.OrderByDescending(t => t.Id).First();
}

class test
{
    public int Id { get; set; }
}

其他回答

你为什么不试试这个??:

var itemsMax = items.Where(x => x.Height == items.Max(y => y.Height));

或者更优化:

var itemMaxHeight = items.Max(y => y.Height);
var itemsMax = items.Where(x => x.Height == itemMaxHeight);

嗯?

先排序,然后再选择第一件商品是浪费大量时间。你不关心它们的顺序。

相反,您可以使用聚合函数来根据您正在寻找的内容选择最佳项目。

var maxHeight = dimensions
    .Aggregate((agg, next) => 
        next.Height > agg.Height ? next : agg);

var maxHeightAndWidth = dimensions
    .Aggregate((agg, next) => 
        next.Height >= agg.Height && next.Width >= agg.Width ? next: agg);

我相信按你想要的列排序,然后抓取第一个应该是可行的。然而,如果有多个对象具有相同的MAX值,则只有一个对象会被抓取:

private void Test()
{
    test v1 = new test();
    v1.Id = 12;

    test v2 = new test();
    v2.Id = 12;

    test v3 = new test();
    v3.Id = 12;

    List<test> arr = new List<test>();
    arr.Add(v1);
    arr.Add(v2);
    arr.Add(v3);

    test max = arr.OrderByDescending(t => t.Id).First();
}

class test
{
    public int Id { get; set; }
}

到目前为止的答案都很棒!但我认为需要一种具有以下约束的解决方案:

朴素、简洁的LINQ; O (n)的复杂性; 每个元素对属性求值不要超过一次。

下面就是:

public static T MaxBy<T, R>(this IEnumerable<T> en, Func<T, R> evaluate) where R : IComparable<R> {
    return en.Select(t => new Tuple<T, R>(t, evaluate(t)))
        .Aggregate((max, next) => next.Item2.CompareTo(max.Item2) > 0 ? next : max).Item1;
}

public static T MinBy<T, R>(this IEnumerable<T> en, Func<T, R> evaluate) where R : IComparable<R> {
    return en.Select(t => new Tuple<T, R>(t, evaluate(t)))
        .Aggregate((max, next) => next.Item2.CompareTo(max.Item2) < 0 ? next : max).Item1;
}

用法:

IEnumerable<Tuple<string, int>> list = new[] {
    new Tuple<string, int>("other", 2),
    new Tuple<string, int>("max", 4),
    new Tuple<string, int>("min", 1),
    new Tuple<string, int>("other", 3),
};
Tuple<string, int> min = list.MinBy(x => x.Item2); // "min", 1
Tuple<string, int> max = list.MaxBy(x => x.Item2); // "max", 4

在NHibernate中(使用NHibernate. linq),你可以这样做:

return session.Query<T>()
              .Single(a => a.Filter == filter &&
                           a.Id == session.Query<T>()
                                          .Where(a2 => a2.Filter == filter)
                                          .Max(a2 => a2.Id));

它将生成如下所示的SQL:

select *
from TableName foo
where foo.Filter = 'Filter On String'
and foo.Id = (select cast(max(bar.RowVersion) as INT)
              from TableName bar
              where bar.Name = 'Filter On String')

这对我来说很有效。