因此,独特的是基于独特的月/年,而不仅仅是一个不同的月份(所以我希望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)
*/
答案 0 :(得分:7)
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));
答案 1 :(得分:4)
您可以创建自己的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();
答案 2 :(得分:2)
var uniqueMonthYears = CompleteListOfDates
.GroupBy(d => new{ d.Month, d.Year})
.Select(my => new DateTime(my.Key.Year, my.Key.Month, 1));
会给你一个IEnumerable<DateTime>
。
编辑:大卫B的回答更好,但是可以选择这个。
答案 3 :(得分:1)
这是我所知道的最短代码:
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);
}
答案 4 :(得分:1)
像
这样的东西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;
}
}
答案 5 :(得分:0)
噢!每个人都打败了我。 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();
哦,还有奖励积分...如果你还没有,请从http://www.linqpad.net/下载Linqpad你可以很容易地尝试这种东西。