如何从通用日期列表中选择不同的日期(按唯一的月份/年份)

本文关键字:日期 唯一 年份 列表 选择 | 更新日期: 2023-09-27 18:19:30

所以distinct是基于唯一的月/年,而不仅仅是一个不同的月(所以我希望2011年1月和2012年1月是不同的)

 // Test set of data
        List<DateTime> CompleteListOfDates = new List<DateTime>();
        CompleteListOfDates.Add(new DateTime(2011, 1, 1));
        CompleteListOfDates.Add(new DateTime(2011, 1, 5));
        CompleteListOfDates.Add(new DateTime(2011, 3, 1));
        CompleteListOfDates.Add(new DateTime(2011, 5, 1));
        CompleteListOfDates.Add(new DateTime(2011, 5, 1));
        CompleteListOfDates.Add(new DateTime(2012, 1, 1));
        CompleteListOfDates.Add(new DateTime(2012, 2, 1));
        List<DateTime> UniqueMonthYears = new List<DateTime>();
        /* need distinct list of DateTimes that are distinct by Month and Year and should be in UniqueMonthYears
         For example:
        new DateTime(2011, 1, 1)
        new DateTime(2011, 3, 1)
        new DateTime(2011, 5, 1)
        new DateTime(2012, 1, 1)
        new DateTime(2012, 2, 1)
        */

如何从通用日期列表中选择不同的日期(按唯一的月份/年份)

List<DateTime> result = source
  .Select(d => new DateTime(d.Year, d.Month, 1))
  .Distinct()
  .ToList();

同样有用:

ILookup<DateTime, Order> ordersByMonth = ordersSource
  .ToLookup(order => new DateTime(order.OrderDate.Year, order.OrderDate.Month, 1));

您可以创建自己的IEqualityComparer实现,然后让Linq来完成剩下的工作,如下所示:

// implement this
public class DateTimeComparer : IEqualityComparer<DateTime>
{
    public bool Equals(DateTime x, DateTime y)
    {
        return x.Year == y.Year && x.Month == y.Month;
    }
    public int GetHashCode(DateTime obj)
    {
        return obj.Year * 100 + obj.Month;
    }
}
// use it like this
UniqueMonthYears = CompleteListOfDates.Distinct(new DateTimeComparer()).ToList();
var uniqueMonthYears = CompleteListOfDates
                          .GroupBy(d => new{ d.Month, d.Year})
                          .Select(my => new DateTime(my.Key.Year, my.Key.Month, 1));

会给你一个IEnumerable<DateTime>

编辑:大卫·B的答案更好,但这里留作选择。

像这样的东西怎么样

completeListOfDates.Select(d => new {Year = d.Year, Month = d.Month}).Distinct()

保留第一天出现的部分基本上没有意义,但你可以这样做。

completeListOfDates.Distinct(new YearMonthComparer());
private class YearMonthComparer : IEqualityComparer<DateTime>
{
    public bool Equals(DateTime x, DateTime y)
    {
        if(x.Year != y.Year) return false;
        if(x.Month != y.Month) return false;
        return true;
    }
    public int GetHashCode(DateTime obj)
    {
        int hash = 13;
        hash = (hash * 7) + obj.Year.GetHashCode();
        hash = (hash * 7) + obj.Month.GetHashCode();
        reutrn hash;
    }
}

这是我所知道的最短的代码:

    List<DateTime> UniqueMonthYears = 
        CompleteListOfDates.Select(t => new DateTime(t.Year, t.Month, 1))
            .Distinct()
            .ToList();

这里有一种更具结构性但性能较差的方法(仅用于演示目的)。它提供了设置string GetHash(Date)Date CreateFromHash(string)函数的能力,从而使其更通用。

代码:

private void Form1_Load(object sender, EventArgs e)
        {
            List<DateTime> CompleteListOfDates = new List<DateTime>();
            CompleteListOfDates.Add(new DateTime(2011, 1, 1));
            CompleteListOfDates.Add(new DateTime(2011, 1, 5));
            CompleteListOfDates.Add(new DateTime(2011, 3, 1));
            CompleteListOfDates.Add(new DateTime(2011, 5, 1));
            CompleteListOfDates.Add(new DateTime(2011, 5, 1));
            CompleteListOfDates.Add(new DateTime(2012, 1, 1));
            CompleteListOfDates.Add(new DateTime(2012, 2, 1));
            List<DateTime> UniqueMonthYears = 
                CompleteListOfDates.Select(t => 
                    GetDateHash(t)).Distinct().Select(t => 
                        CreateFromDateHash(t)).ToList();

            MessageBox.Show(UniqueMonthYears.Count.ToString());
        }
        private static string GetDateHash(DateTime date)
        {
            return date.ToString("MMM-yyyy");
        }
        private static DateTime CreateFromDateHash(string hash)
        {
            return DateTime.Parse("1-" + hash);
        }

Aw!每个人都打败了我。LINQ的问题非常有趣

我不知道你想如何从列表中选择唯一的日期,所以我没有假设你想放弃它,而是在子查询中使用了First方法。很明显,你可以使用某种类型的谓词来改变这一点。

那这个怎么样?

var UniqueMonthYears = (from date in CompleteListOfDates
                        let month = date.Month
                        let year = date.Year
                        let day = (CompleteListOfDates.First(d => d.Month == month && d.Year == year))
                        select day).Distinct();

哦,还有奖励积分。。。如果您还没有,请从下载Linqpadhttp://www.linqpad.net/你可以很容易地尝试这种东西。