簡體   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