使用 LINQ 从一系列日期中获取不同的日期

Fetching Distinct dates from a range of dates using LINQ

我一直在尝试根据 table 的最新时间仅获取不同日期的列表,其中我在给定范围内重复日期。即

给定范围;

Start Date: 11/1/2017 12:00:00 AM
End Date: 11/20/2017 12:00:00 AM 

使用查询;

var mod = (from m in lstMachineInfo
             where m.RegisterationId == EnrollNumber 
                && m.Date >= startDate 
                && m.Date <= endDate
             select m).Distinct();

我得到的是;

11/9/2017 8:02:09 AM    
11/9/2017 3:22:51 PM    
11/9/2017 5:09:23 PM    
11/10/2017 11:23:04 AM  
11/10/2017 4:19:57 PM   
11/14/2017 10:11:11 AM  
11/14/2017 6:30:30 PM   

我要的是;

11/9/2017 8:02:09 AM    
11/10/2017 11:23:04 AM  
11/14/2017 10:11:11 AM
var earlyMod = mod
    .GroupBy(dt => dt.Value.Date)
    .Select(z => z.OrderBy(y => y.Date).First())
    .ToList();

earlyMod 将 return 每个给定日期的最早时间。这将在数​​据库外部执行(如果给定日期中不同时间记录的数量有限,这会很好)。

如果您希望它在数据库的内部执行,请尝试:

var mod = (from m in lstMachineInfo
             where m.RegisterationId == EnrollNumber 
                && m.Date >= startDate 
                && m.Date <= endDate
             select m)
           .GroupBy(a => EntityFunctions.TruncateTime(a.Value.Date))
           .Select(z => z.OrderBy(y => y.Date).First()).ToList();

您可以为此使用 MoreLinq 的 DistinctBy。 (您可以通过 NuGet 安装它。)

那么你可以这样做:

using System;
using MoreLinq;

namespace Demo
{
    class Program
    {
        static void Main()
        {
            var dates = new []
            {
                new DateTime(2017, 11, 9, 8, 2, 9),
                new DateTime(2017, 11, 9, 5, 9, 23),
                new DateTime(2017, 11, 9, 15, 22, 51),
                new DateTime(2017, 11, 9, 17, 9, 23),
                new DateTime(2017, 11, 10, 11, 23, 04),
                new DateTime(2017, 11, 10, 16, 19, 57),
                new DateTime(2017, 11, 14, 10, 11, 11),
                new DateTime(2017, 11, 14, 18, 30, 30)
            };

            var distinctByDate = dates.OrderBy(date => date).DistinctBy(date => date.Date);

            foreach (var date in distinctByDate)
                Console.WriteLine(date);
        }
    }
}

或者如果日期可以为空,则必须过滤掉空值:

        var dates = new DateTime?[]
        {
            new DateTime(2017, 11, 9, 17, 9, 23),
            new DateTime(2017, 11, 9, 15, 22, 51),
            new DateTime(2017, 11, 9, 8, 2, 9),
            null,
            new DateTime(2017, 11, 10, 11, 23, 04),
            new DateTime(2017, 11, 9, 17, 9, 23),
            null,
            new DateTime(2017, 11, 14, 10, 11, 11),
            new DateTime(2017, 11, 10, 16, 19, 57),
            new DateTime(2017, 11, 14, 18, 30, 30)
        };

        var distinctByDate = dates.Where(date => date.HasValue).OrderBy(date => date).DistinctBy(date => date?.Date);

        foreach (var date in distinctByDate)
            Console.WriteLine(date);
    }

请注意,如果保证日期已经安排妥当,您可以省略 OrderBy()


为了完整性,这里是 DistinctBy 的实现(我相信这是 Jon Skeet 最先提供的):

public static class EnumerableDistinctExt
{
    public static IEnumerable<TSource> DistinctBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
    {
        return source.DistinctBy(keySelector, null);
    }

    public static IEnumerable<TSource> DistinctBy<TSource, TKey>(
        this IEnumerable<TSource> source, 
        Func<TSource, TKey> keySelector, 
        IEqualityComparer<TKey> comparer)
    {
        return distinctByImpl(source, keySelector, comparer);
    }

    static IEnumerable<TSource> distinctByImpl<TSource, TKey>(
        IEnumerable<TSource> source,
        Func<TSource, TKey> keySelector,
        IEqualityComparer<TKey> comparer)
    {
        var knownKeys = new HashSet<TKey>(comparer);
        return source.Where(element => knownKeys.Add(keySelector(element)));
    }
}