pátek 8. dubna 2016

Linq - k čemu použít Aggregate

K jednomu z předchozích článků, ve kterém jsem dal k dispozici cheatsheet pro Linq, se mne jeden známý zeptal, k čemu že je dobrý Aggregate - vždy si zatím vystačil například se Sum, Count či Average.

Nejlépe se vysvětluje na příkladě a zabrousím do oblasti hudebních alb: máme řetězec obsahující seznam délek jednotlivých skladeb a chceme získate celkový čas alba. 

Úkol jak stvořený pro Linq.
var trackTimes = "1:20,5:40,6:20, 10:40";

Nejprve si z řetězce uděláme kolekci jednotlivých délek, k tomu poslouží Split:
.Split(',')
Nyní jednotlivé prvky převedeme na datový typ TimeSpan:
.Select(i => TimeSpan.ParseExact(i.Trim(), @"m\:s", null))
A nyní nám to zbývá jen sečíst. Nabízí se Sum, ale ejhle, funguje jen pro číselné datové typy. Ale na vše ostatní je zde právě Aggregate a tak stačí napsat:
.Aggregate(TimeSpan.Zero, (t1, t2) => t1 + t2);
TimeSpan.Zero není nutné použít, je to jen náznak, jak si můžeme něco přičíst k výsledné hodnotě hned na začátku (tady tedy nulu :-). Výsledný kód pak vypadá takto:

internal class Program
{
   private static void Main(string[] args)
   {
      var trackTimes = "1:20,5:40, 6:20";
      Console.WriteLine($"Total time is {GetTotalTime(trackTimes)}.");
   }
 
   private static TimeSpan GetTotalTime(string trackTimes)
   {
      return trackTimes
               .Split(',')
               .Select(i => TimeSpan.ParseExact(i.Trim(), @"m\:s", null))
               .Aggregate(TimeSpan.Zero, (t1, t2) => t1 + t2);
   }
}
Samozřejmě lze kód napsat i s použitím Sum:
private static TimeSpan GetTotalTime(string trackTimes)
{
   return
      TimeSpan.FromSeconds(
         trackTimes
            .Split(',')
            .Select(i => TimeSpan.ParseExact(i.Trim(), @"m\:s", null))
            .Sum(t => t.TotalSeconds)
      );
}

Žádné komentáře:

Okomentovat