所以,我有一个看起来像这样的列表。它基本上是一堆项目的状态历史,最近的状态代表当前状态。
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,但我不能完全把它们放在一起。
答案 0 :(得分:9)
myList.GroupBy(m => m.Id)
.Select(g => g.OrderByDescending(x => x.Date).First())
.Where(<your filter>);
答案 1 :(得分:2)
这里有一些代码可以做你想要的。它获取每个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”。
答案 2 :(得分:1)
如果这是LINQ to Objects(假设记录按正确的顺序排列),你可以这样做:
var latestById = records.GroupBy(record => record.Id)
.ToDictionary(group => group.Key, group => group.Last());
这是因为GroupBy guarantees that“分组中的元素按它们在源中出现的顺序产生。”
如果您无法保证记录顺序,我会这样做:
var latestById = records.GroupBy(record => record.Id)
.Select(group => group.MaxBy(r => r.Date))
.ToDictionary(record => record.Id);
顺便说一句,如果这是LINQ to SQL,我会这样做:
var latestById = records.GroupBy(record => record.Id)
.Select(group => group.OrderByDescending(r => r.Date).First())
.AsEnumerable()
.ToDictionary(record => record.Id);