我有一个具有两个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; }
}

其他回答

我们在MoreLINQ中有一个扩展方法可以做到这一点。你可以看看这里的实现,但基本上这是一个遍历数据的例子,记住我们迄今为止看到的最大元素以及它在投影下产生的最大值。

在你的情况下,你会这样做:

var item = items.MaxBy(x => x.Height);

这比这里提出的除Mehrdad的第二个解决方案(基本上与MaxBy相同)之外的任何解决方案都更好(IMO):

它是O(n)不像之前接受的答案,它在每次迭代中找到最大值(使它成为O(n²)) 排序解是O(n log n) 取Max值,然后找到具有该值的第一个元素是O(n),但在序列上迭代两次。在可能的情况下,应该以单遍方式使用LINQ。 它比聚合版本更容易阅读和理解,并且每个元素只计算一次投影

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

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

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

根据Cameron最初的回答,以下是我刚刚在SilverFlow库的FloatingWindowHost的增强版本中添加的内容(从http://clipflair.codeplex.com源代码中的FloatingWindowHost.cs复制)

    public int MaxZIndex
    {
      get {
        return FloatingWindows.Aggregate(-1, (maxZIndex, window) => {
          int w = Canvas.GetZIndex(window);
          return (w > maxZIndex) ? w : maxZIndex;
        });
      }
    }

    private void SetTopmost(UIElement element)
    {
        if (element == null)
            throw new ArgumentNullException("element");

        Canvas.SetZIndex(element, MaxZIndex + 1);
    }

值得注意的是Canvas上面的代码。ZIndex是一个附加属性,可用于各种容器中的uielement,而不仅仅是在Canvas中托管时使用(参见在Silverlight中不使用Canvas控件控制渲染顺序(ZOrder))。我猜你甚至可以通过修改这段代码为UIElement创建一个SetTopmost和SetBottomMost静态扩展方法。

在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')

这对我来说很有效。

我相信按你想要的列排序,然后抓取第一个应该是可行的。然而,如果有多个对象具有相同的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; }
}