2009-10-28 3 views
0

Основная проблема: как мне группировать элементы по их дате, только если они непрерывны и только если они соответствуют некоторым свойствам?Linq непрерывная дата takewhile

Детали:

Учитывая этот тип объекта:

public class MyObj 
{ 
    public DateTime Date { get; set; } 
    public string ConditionalValue1 { get; set; } 
    public int ConditionalValue2 { get; set; } 
    public int OtherValue { get; set; } 

    //for test purposes only, i would like to avoid doing this 
    public bool CompareFields(MyObj toBeCompared) 
    { 
     return ConditionalValue1 == toBeCompared.ConditionalValue1 && 
       ConditionalValue2 == toBeCompared.ConditionalValue2; 
    } 
} 

У меня есть список из них, заполняется следующим образом:

//list is ordered for semplicity, but it won't be by default 
//list is a result of a group by too 
var myList = new[] 
{ 
    new MyObj { Date = new DateTime(2009, 10, 20), ConditionalValue1 = "A", ConditionalValue2 = 1, OtherValue = 1 }, 
    new MyObj { Date = new DateTime(2009, 10, 21), ConditionalValue1 = "A", ConditionalValue2 = 1, OtherValue = 2 }, 
    new MyObj { Date = new DateTime(2009, 10, 22), ConditionalValue1 = "B", ConditionalValue2 = 1, OtherValue = 3 }, 
    new MyObj { Date = new DateTime(2009, 10, 23), ConditionalValue1 = "A", ConditionalValue2 = 2, OtherValue = 4 }, 
    new MyObj { Date = new DateTime(2009, 10, 24), ConditionalValue1 = "A", ConditionalValue2 = 2, OtherValue = 5 }, 
    new MyObj { Date = new DateTime(2009, 10, 25), ConditionalValue1 = "A", ConditionalValue2 = 1, OtherValue = 6 }, 
    //Note the hole for day 26 
    new MyObj { Date = new DateTime(2009, 10, 27), ConditionalValue1 = "A", ConditionalValue2 = 1, OtherValue = 7}, 
}; 

Wanted (псевдокод):

List = 
    { ListOfObjects }, //First has date = "2009/10/20", last has = "2009/10/21" 
    { ListOfObjects }, //First has date = "2009/10/22", last has = "2009/10/22" //reason: doesn't match Value1 
    { ListOfObjects }, //First has date = "2009/10/23", last has = "2009/10/24" 
    { ListOfObjects }, //First has date = "2009/10/25", last has = "2009/10/25" //reason: doesn't match Value2 
    { ListOfObjects } //First has date = "2009/10/27", last has = "2009/10/27" //reason: there is no "2009/10/26" object 

тесты до сих пор:

//i pick the first element, to be compared with the next ones 
var firstInList = myList.First(); 
//take while date is consequent and fields are compared 
var partialList = myList 
    .TakeWhile(
     (obj, index) => obj.Date == firstInList.Date.AddDays(index) && 
         obj.CompareFields(firstInList) 
    ); 

Это частично работает, а, конечно, он будет возвращать правильные результаты только для первых согласующих элементов.

Я не мог Skip(count) список до 0 элементов, но я хотел бы использовать group by, используя IEqualityComparer вместо метода CompareFields.

ответ

2

Возможно, вы сможете использовать Enumerable.GroupBy. Тем не менее, у меня такое чувство, что он может пройти через весь набор. Если это так, вы всегда можете создать свой собственный метод расширения SequencedGroupBy.

Предупреждение: не будет работать с параллельными расширениями (AsParallel)

DateTime lastGroupDate = DateTime.MinValue; 
DateTime lastDate = DateTime.MinValue; 

IEnumerable<IGrouping<DateTime, MyObj>> groups = myList 
    .GroupBy(o => 
     { 
      if (lastGroupDate != DateTime.MinValue && 
       o.Date.AddDays(-1) == lastDate) 
      { 
       lastDate = o.Date; 
      } 
      else 
      { 
       lastGroupDate = o.Date; 
       lastDate = o.Date; 
      } 

      return lastGroupDate; 
     } 
    ); 

foreach(IGrouping<DateTime, MyObj> grouping in groups) 
{ 
    // grouping.Key == the grouped date/first in sequence 

    foreach(MyObj obj in grouping) 
    { 
     // obj.Date == actual date 
    } 
} 
+0

хороший, но как я могу добавить другие условия для группировки тоже? –

+0

Зависит от того, что вы имеете в виду. Более сложный ключ -> используйте struct. Более сложные сравнения -> измените 'DateTime lastDate' на' MyObj lastObj', чтобы вы могли сравнить с другими свойствами. –

+0

Прошу прощения, я не могу понять, как это должно работать. Предположим, я хочу сгруппировать все элементы с соответствующими датами, но также и SAME ConditionalValue1. Как мне это сделать? –

 Смежные вопросы

  • Нет связанных вопросов^_^