Yani, biz bu jenerik yineleyici fonksiyonu ile dışarı başlayacağız. Bir diziyi ve iki öğeyi kabul eden ve bir boole döndüren bir yüklemi alır. Kaynaktaki öğelerde okunacak ve bir öğe, önceki öğeyle birlikte, yüklemeye dayalı olarak true değerini döndürür, sonraki öğe "sonraki grupta" olacaktır. Yanlış döndürürse, önceki grup dolu ve sonraki grup başlatılır.
public static IEnumerable<IEnumerable<T>> GroupWhile<T>(this IEnumerable<T> source
, Func<T, T, bool> predicate)
{
using (var iterator = source.GetEnumerator())
{
if (!iterator.MoveNext())
yield break;
List<T> currentGroup = new List<T>() { iterator.Current };
while (iterator.MoveNext())
{
if (predicate(currentGroup.Last(), iterator.Current))
currentGroup.Add(iterator.Current);
else
{
yield return currentGroup;
currentGroup = new List<T>() { iterator.Current };
}
}
yield return currentGroup;
}
}
Ayrıca, bir sonraki çalışma gününü bir tarihe dayanan bu basit yardımcı yönteme de ihtiyacımız var. Tatilleri de birleştirmek istiyorsanız, önemsizden oldukça zoruna gider, ama mantığın gideceği yer burasıdır.
public static DateTime GetNextWorkDay(DateTime date)
{
DateTime next = date.AddDays(1);
if (next.DayOfWeek == DayOfWeek.Saturday)
return next.AddDays(2);
else if (next.DayOfWeek == DayOfWeek.Sunday)
return next.AddDays(1);
else
return next;
}
Şimdi hepsini bir araya getirmek için. Önce günleri sipariş ediyoruz. (Her zaman emrettiğinizden emin olursanız, o bölümü kaldırabilirsiniz.) Ardından, her bir öğe bir önceki işin sonraki iş günü iken ardışık öğeleri gruplandırırız.
Yapmamız gereken tek şey, bir IEnumerable<DateTime>
ardışık tarihini NonWorkingDay
'a dönüştürmektir. Bunun için başlangıç tarihi ilk tarihtir ve Days
dizinin sayısıdır. Normalde iki kez kaynak dizisini yineleme olur hem First
ve Count
kullanırken, biz GroupWhile
tarafından döndürülen dizi aslında başlık altında bir List
olduğunu biliyor, bu yüzden birden çok kez yineleme bir sorun değildir ve Count
alma hatta O (olduğu 1).
public IEnumerable<NonWorkingDay> GetContiguousDates(IEnumerable<DateTime> dates)
{
return dates.OrderBy(d => d)
.GroupWhile((previous, next) => GetNextWorkDay(previous).Date == next.Date)
.Select(group => new NonWorkingDay
{
Start = group.First(),
Days = group.Count(),
});
}
Güzel bulmaca! ... – spender
GrupBir hafta sonra Gruptaki öğeleri sayabilir misiniz? Haftalığa göre gruplama burada bulunabilir http://stackoverflow.com/questions/8561782/how-to-group-dates-by-week – bUKaneer
Hayır, çünkü orada pazartesi-cuma 2.5 haftadır diyebiliriz ki orada – jmasterx