Don't like ads? PRO users don't see any ads ;-)
Guest

Untitled

By: a guest on Jul 14th, 2012  |  syntax: None  |  size: 5.31 KB  |  hits: 10  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. LINQ aggregate 30 minute interval to hour
  2. Start: 6:00
  3. End: 6:30
  4. value: 1
  5. Start: 7:00
  6. End: 7:30
  7. value: 1
  8. Start: 8:00
  9. End: 8:30
  10. value: 1
  11. Start: 9:00
  12. End: 9:30
  13. value: 1
  14. Start: 10:00
  15. End: 10:30
  16. value: 1
  17. Start: 11:00
  18. End: 11:30
  19. value: 1
  20. Start: 12:00
  21. End: 12:30
  22. value: 1
  23. Start: 13:00
  24. End: 13:30
  25. value: 1
  26. Start: 14:00
  27. End: 14:30
  28. value: 1
  29. ...
  30. Start: 05:00
  31. End: 05:30
  32. value: 1
  33.        
  34. Start: 6:00
  35. End: 7:00
  36. Value: 2
  37. Start:7:00
  38. End: 8:00
  39. Value:2
  40. ......
  41.        
  42. private enum AggerationType { Year = 1, Month = 2, Day = 3, Hour = 4 }
  43.  
  44. private IList<Data> RunQuery(AggerationType groupType, AggerationType checkType)
  45. {
  46.     // The actual query which does to trick
  47.     var result =
  48.         from d in testList
  49.         group d by new {
  50.             d.Start.Year,
  51.             Month = (int)groupType >= (int)AggerationType.Month ? d.Start.Month : 1,
  52.             Day = (int)groupType >= (int)AggerationType.Day ? d.Start.Day : 1,
  53.             Hour = (int)groupType >= (int)AggerationType.Hour ? d.Start.Hour : 1
  54.         } into g
  55.         // The where clause checks how much data needs to be in the group
  56.         where CheckAggregation(g.Count(), checkType)
  57.         select new Data() { Start = g.Min(m => m.Start), End = g.Max(m => m.End), Value = g.Sum(m => m.Value) };
  58.  
  59.     return result.ToList();
  60. }
  61.  
  62. private bool CheckAggregation(int groupCount, AggerationType checkType)
  63. {
  64.     int requiredCount = 1;
  65.     switch(checkType)
  66.     {
  67.         // For year all data must be multiplied by 12 months
  68.         case AggerationType.Year:
  69.             requiredCount = requiredCount * 12;
  70.             goto case AggerationType.Month;
  71.         // For months all data must be multiplied by days in month
  72.         case AggerationType.Month:
  73.             // I use 30 but this depends on the given month and year
  74.             requiredCount = requiredCount * 30;
  75.             goto case AggerationType.Day;
  76.         // For days all data need to be multiplied by 24 hour
  77.         case AggerationType.Day:
  78.             requiredCount = requiredCount * 24;
  79.             goto case AggerationType.Hour;
  80.         // For hours all data need to be multiplied by 2 (because slots of 30 minutes)
  81.         case AggerationType.Hour:
  82.             requiredCount = requiredCount * 2;
  83.             break;
  84.  
  85.     }
  86.     return groupCount == requiredCount;
  87. }
  88.        
  89. class Data
  90. {
  91.     public DateTime Start { get; set; }
  92.     public DateTime End { get; set; }
  93.     public int Value { get; set; }
  94. }
  95.  
  96. // Just setup some test data simulary to your example
  97. IList<Data> testList = new List<Data>();
  98. DateTime date = DateTime.Parse("6:00");
  99.  
  100. // This loop fills just some data over several years, months and days
  101. for (int year = date.Year; year > 2010; year--)
  102. {
  103.     for(int month = date.Month; month > 0; month--)
  104.     {
  105.         for (int day = date.Day; day > 0; day--)
  106.         {
  107.             for(int hour = date.Hour; hour > 0; hour--)
  108.             {
  109.                 DateTime testDate = date.AddHours(-hour).AddDays(-day).AddMonths(-month).AddYears(-(date.Year - year));
  110.                 testList.Add(new Data() { Start = testDate, End = testDate.AddMinutes(30), Value = 1 });
  111.                 testList.Add(new Data() { Start = testDate.AddMinutes(30), End = testDate.AddHours(1), Value = 1 });
  112.             }
  113.         }
  114.     }
  115. }
  116.        
  117. var items = input.Split('n');
  118.  
  119. Func<string, string> f = s =>
  120. {
  121.     var strings = s.Split(new[] {':'}, 2);
  122.     var key = strings[0];
  123.     var value = strings[1];
  124.  
  125.     switch (key.ToLower())
  126.     {
  127.         case "start":
  128.             return s;
  129.         case "value":
  130.             return String.Format("{0}: {1}", key, Int32.Parse(value) + 1);
  131.         case "end":
  132.             return String.Format("{0}: {1:h:mm}", key,
  133.                 DateTime.Parse(value) +
  134.                 TimeSpan.FromMinutes(30));
  135.         default:
  136.             return "";
  137.     }
  138. };
  139.  
  140. var resultItems = items.Select(f);
  141.  
  142. Console.Out.WriteLine("result = {0}",
  143.                           String.Join(Environment.NewLine, resultItems));
  144.        
  145. class TimeInterval
  146. {
  147.     DateTime Start;
  148.     DateTime End;
  149.     int Value;
  150. }
  151.  
  152. IEnumerable<TimeInterval> ToHourlyIntervals(
  153.     IEnunumerable<TimeInterval> halfHourlyIntervals)
  154. {
  155.     return
  156.         from pair in Split(halfHourlyIntervals)
  157.         select new TimeInterval
  158.         {
  159.             Start = pair.Item1.Start,
  160.             End = pair.Item2.End,
  161.             Value = pair.Item1.Value + pair.Item2.Value
  162.         };
  163. }
  164.  
  165. static IEnumerable<Tuple<T, T>> Split<T>(
  166.     IEnumerable<T> source)
  167. {
  168.     using (var enumerator = source.GetEnumerator())
  169.     {
  170.         while (enumerator.MoveNext())
  171.         {
  172.             T first = enumerator.Current;
  173.  
  174.             if (enumerator.MoveNext())
  175.             {            
  176.                 T second = enumerator.Current;
  177.                 yield return Tuple.Create(first, second);
  178.             }
  179.         }
  180.     }
  181. }
  182.        
  183. IEnumerable<TimeInterval> ToHalfHourlyIntervals(
  184.     IEnumerable<string> inputLines)
  185. {
  186.     return
  187.         from triple in TripleSplit(inputLines)
  188.         select new TimeInterval
  189.         {
  190.             Start = DateTime.Parse(triple.Item1.Replace("Start: ", "")),
  191.             End = DateTime.Parse(triple.Item2.Replace("End: ", "")),
  192.             Value = Int32.Parse(triple.Item3)
  193.         };
  194. }
  195.        
  196. // Read data lazilzy from disk (or any other source)
  197. var lines = File.ReadLines(path);
  198.  
  199. var halfHourlyIntervals = ToHalfHourlyIntervals(lines);
  200.  
  201. var hourlyIntervals = ToHourlyIntervals(halfHourlyIntervals);
  202.  
  203. foreach (var interval in hourlyIntervals)
  204. {
  205.     // process
  206. }