LINQ 연속 날짜 테이크
-
08-07-2019 - |
문제
주요 문제 : 날짜까지 요소를 어떻게 그룹화합니까?
세부:
이 유형의 객체가 주어지면 :
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},
};
원해 (의사 코드) :
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
.
해결책
당신은 사용할 수 있습니다 열거 가능. 그러나 전체 세트를 통해 루프 할 수 있다고 생각합니다. 그렇다면 항상 자신만의 시퀀싱 Groupby 확장 방법을 만들 수 있습니다.
경고: 평행 연장 (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
}
}
제휴하지 않습니다 StackOverflow