如何从通用日期列表中选择不同的日期(按唯一的月份/年份)
本文关键字:日期 唯一 年份 列表 选择 | 更新日期: 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/你可以很容易地尝试这种东西。