簡體   English   中英

Linq查詢對每個組中的項目和查詢進行分組

[英]Linq query to group items and query from the top item in each group

所以,我有一個看起來像這樣的列表。 它基本上是一堆物品的狀態歷史,最近的狀態代表當前狀態。

Record   Id      State       Date
=====    ===     =========  =======
1        A       Waiting     Jan 01
2        A       InProgress  Jan 02
3        A       Finished    Jan 03
4        B       Waiting     Jan 02
5        C       Waiting     Jan 01
6        C       InProgress  Jan 02
7        D       Waiting     Jan 01
8        D       InProgress  Jan 02

我正在尋找的是能夠查詢每個項目的“當前”狀態。 例如,我想說:“給我所有的ID都是'InProgress'”並獲得Id D和Id C,但不是Id A(因為它的最新狀態是'完成')。

我知道我必須做一些分組和一些訂購或Maxing,但我不能完全把它放在一起。

myList.GroupBy(m => m.Id)
.Select(g => g.OrderByDescending(x => x.Date).First())
.Where(<your filter>);

這里有一些代碼可以做你想要的。 它獲取每個id的最新狀態並忽略已完成的記錄。 我已經提供了一個完整的工作示例,您可以運行(並希望適應您的實際數據)。

//the example data provided by the OP
var data = new []
{
    new { Record = 1, Id = "A", State = "Waiting", Date = new DateTime(2013, 1, 1) },
    new { Record = 2, Id = "A", State = "InProgress", Date = new DateTime(2013, 1, 2) },
    new { Record = 3, Id = "A", State = "Finished", Date = new DateTime(2013, 1, 3) },        
    new { Record = 4, Id = "B", State = "Waiting", Date = new DateTime(2013, 1, 1) },        
    new { Record = 5, Id = "C", State = "Waiting", Date = new DateTime(2013, 1, 1) },
    new { Record = 6, Id = "C", State = "InProgress", Date = new DateTime(2013, 1, 2) },        
    new { Record = 7, Id = "D", State = "Waiting", Date = new DateTime(2013, 1, 1) },
    new { Record = 8, Id = "D", State = "InProgress", Date = new DateTime(2013, 1, 2) },
};

var query = from d in data
            //put the newest record first
            orderby d.Date descending
            //group by the id
            group d by d.Id into groupedById
            //get the latest record for each id
            let latest = groupedById.First()
            //filter out finished records
            where latest.State != "Finished"
            select latest;

這是LinqPad的輸出。

在此輸入圖像描述

你會注意到我們每個項目都有最新的狀態,除了因為它已經完成而被忽略的“A”。

如果這是對象的LINQ(並假設記錄按正確的順序排列),您可以:

var latestById = records.GroupBy(record => record.Id)
                        .ToDictionary(group => group.Key, group => group.Last());

這是因為GroupBy 保證 “分組中的元素按它們在源中出現的順序產生”。

如果你不能保證記錄順序,我會這樣做:

var latestById = records.GroupBy(record => record.Id)
                        .Select(group => group.MaxBy(r => r.Date))
                        .ToDictionary(record => record.Id);

其中MaxBy來自moreLinq

順便說一句,如果這是LINQ to SQL,我會這樣做:

var latestById = records.GroupBy(record => record.Id)
                        .Select(group => group.OrderByDescending(r => r.Date).First())
                        .AsEnumerable()
                        .ToDictionary(record => record.Id);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM