繁体   English   中英

选择清单 <T> 使用LINQ查询获得最大值的项目

[英]Select List<T> item with max value using LINQ query

我有List loadRecords,其中T类型定义如下

public class TransformerLoadRecord
{

    public double TotalLoadKva { get; set; }
    public double TotalLoadKwh { get; set; }
    public string LoadDate { get; set; }
    public string LoadTime { get; set; }
    public long Fid { get; set;}
    public string UserId { get; set; }
    public string SessionId { get; set; }



    public override string ToString()
    {
        return "User Id:" + UserId +
               " Session Id:" + SessionId +
               " Fid:" + Fid.ToString() +
               " Load Date:" + LoadDate + 
               " Load Time:" + LoadTime + 
               " Total Load KWH:" + TotalLoadKwh.ToString() + 
               " Total Load KVA:" + TotalLoadKva.ToString();
    }
}

我需要从项目列表中获取最大TotalLoadKva的项目(大约1900)

var mxKVALoad = loadRecords.Max(l => l.TotalLoadKva);

但是我需要所有其他属性,并且此代码不起作用并且返回多个项目

var maxLoadRecord = from txLoadValues in loadRecords 
                    group txLoadValues by txLoadValues.TotalLoadKva 
                         into txLoadValueGroup 
                     select txLoadValueGroup.OrderByDescending(l => l.TotalLoadKva).FirstOrDefault();

我在这里做错了什么? 你能解释一下吗?

谢谢。

我不这么认为,你需要将它们分组只是为了获得创纪录的最高TotalLoadKva ,你可以使用OrderByDescending给它们排序TotalLoadKva ,然后选择使用顶部第一条记录FirstFirstOrDefault方法:

var maxKVALoad = loadRecords.OrderByDescending(l => l.TotalLoadKva).FirstOrDefault();
                 // will return the record with highest value of TotalLoadKva

首选方法是使用FirstOrDefault()因为First()会抛出异常,说明:

序列不包含任何元素

如果保证总是会有返回的行,则可以安全地使用First() ,否则使用FirstOrDefault ,如果collection为空,则不会抛出异常。

您需要对源列表进行排序(降序)并采用第一个元素:

var elementWithMaxKVA = loadRecords.OrderByDescending(l => l.TotalLoadKva).FirstOrDefault();

但这不是最快的方法,因为OrderBy*将要做的工作不仅仅是查找最大值。

您可以改为实现自己的扩展方法,如下所示:

// error handling and argument checks ommitted for brevity
public static TSource MaxBy<TSource, TComp>(this IEnumerable<TSource> source, Func<TSource, TComp> selector) where TComp : IComparable
{    
    using (var enumerator = source.GetEnumerator())
    {
        TSource max = default(TSource);
        TComp maxV = default(TComp);
        if (!enumerator.MoveNext()) return max; // or throw

        max = enumerator.Current;
        maxV = selector(max);

        while(enumerator.MoveNext())
        {
            TSource current = enumerator.Current;
            TComp currentV = selector(current);
            if (currentV.CompareTo(maxV) <= 0) continue;
            maxV = currentV;
            max = current;
        }

        return max;
    }
}

并像这样使用

var elementWithMaxKVA = loadRecords.MaxBy(l => l.TotalLoadKva);

我认为MoreLinq nuget包已经包含了这样的MaxBy方法。

以下应该工作:

var mxKVALoad = loadRecords
                .Where(l => l.totalLoadKva == loadRecords.Max(l => l.TotalLoadKva));

另外,您也可以使用MaxByMoreLINQ

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM