使用LINQ基于日期从列表中删除项目

3
在C#中,我有一个列表locationsList,其中包含字段locationdatelocation可以出现多次,但日期不同。
如果location出现多次,我只想保留最新日期的那一项。是否有使用LINQ而不是迭代整个列表并比较每个多次出现的位置的日期的方法来实现这一目标?

6
请提供您当前代码的[最小化、完整、可复现示例](MCVE)。 - dymanoid
正如dymanoid所提到的,如果没有代码示例,我们无法真正回答这个问题。根据对您重要的字段进行分组处理。 - Flater
1个回答

3
我假设字段location是字符串类型的,你可以重新构建你的位置对象:
class Location {
    public string location { get; set; }
    public DateTime date { get; set; }
}

var distincts = locationsList 
         .GroupBy(location => location.location)
         .Select(grp => new Location {
             location = grp.Key, 
             date = grp.Max(loc => loc.date)
         });

如果重建对象不是一个选项,您可以使用MoreLINQMaxBy扩展方法:
var distincts = locationsList 
         .GroupBy(location => location.location)
         .Select(grp => grp.MaxBy(loc => loc.date))

为简化起见,这里提供了一个非通用版本的MaxBy方法,适用于您的情况:

Location MaxByDate(List<Location> locations){
    Location maxLocation = null;
    var maxDate = DateTime.MinValue;
    foreach(var location in locations) {
        if (location.date > maxDate)
        {
            maxLocation = location;
            maxDate = location.date;
        }
    }
    return maxLocation ;
}

编辑

Flater提出的另一种替代方案,由于您必须在每个组中循环两次,一次检索最大值,第二次循环查找匹配项,因此性能略差。但非常易读和可维护。

var distincts = locationsList 
     .GroupBy(location => location.location)
     .Select(grp => {
         var maxDate = grp.Max(location => location.date);
         return grp.First(location => location.date == maxDate);
     })

3
不使用MoreLINQ也可以完成:Select(group => group.First(x => x.Date == group.Max(y => y.Date))。这种方法略显冗长,但是可行。(请注意,我使用了 First 而不是 FirstOrDefault ,因为在 GroupBy 后逻辑上不可能遇到空值)。 - Flater
2
@Flater,这将计算原始源中每个项目组的“Max”。这将导致可怕的性能。如果您想走这条路,请在调用“First”之前计算最大值。 - Drew Noakes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接