2012-01-04 1 views
2

그래서 서로 다른이 독특한 월/년을 기반으로, 단지 하나의 고유 한 달일반적인 날짜 목록에서 고유 한 월/연도 별 고유 번호를 어떻게 선택합니까?

// 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) 
     */ 
+3

수많은 답변 외에도 MoreLINQ의 DistinctBy 기능이 유용 할 수 있습니다. http://code.google.com/p/morelinq/source/browse/trunk/MoreLinq/DistinctBy.cs –

답변

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)); 
+0

이것은 정확히 내가 찾던 것이 었습니다. 감사합니다. – Shane

1

여기 내가 아는 거라고 짧은 코드입니다 (그래서 나는 별개로 2011 년 월과 2012 년 월 원할 것) :

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); 
     } 
+0

글쎄, 스킬이 충분하지 않습니다 :) –

+0

코드가 GetMonthYear 함수 사용을 시연하지 않는 것 같습니다. 당신이 제안하는 것처럼 보이는데 ... 당신은 당신의 질문을 조금 정리할 수 있습니다. 당신이 글쓰기를 통해 해결책의 절반을 바꾼 것처럼 보입니다 ... – Chris

+0

답변이 게시 된 시간을 보았습니까? :) 투영이 여기에서 훨씬 더 투명하기 때문에 나는 최근에 내 마음을 바꿨다. –

2
var uniqueMonthYears = CompleteListOfDates 
          .GroupBy(d => new{ d.Month, d.Year}) 
          .Select(my => new DateTime(my.Key.Year, my.Key.Month, 1)); 

당신에게 IEnumerable<DateTime>을 줄 것이다.

편집 : David B의 답변이 더 좋지만 옵션으로 남겨 둡니다. 당신은 당신의 자신의 IEqualityComparer 구현을 만들고 Linq에이 같은 나머지 수행하도록 할 수 있습니다

4

:

// 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(); 
+0

나는 IComparer 을 받아들이는 Distinct의 과부하를 알고 있지 않다. 'IEqualityComparer '을 사용할 수 있습니다. –

+0

그래 맞아 ... 고쳐 놨어. – Nuffin

+1

1) 같음은 bool을 반환합니다. 2) 구현에는'int GetHashCode (DateTime value)'가 필요합니다. –

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; 
    } 
} 
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을 다운로드 할 수 있습니다.

관련 문제