Na początku zastąpię proste metody jak suma, count, all i concat za pomocą aggregate.
var ints = Enumerable.Range(0, 10); var sum1 = ints.Sum(); var sum2 = ints.Aggregate( ( agg, item ) => agg + item ); var count1 = ints.Count(); var count2 = ints.Aggregate(0,(agg, item) => agg + 1, x=>x); var median1 = ints.ElementAt(ints.Count()/2); var median2 = ints.Aggregate( 0, ( info, item ) => info = info + 1, x => ints.ElementAt( x / 2 ) ); var all1 = ints.All(x => x > -1); var all2 = ints.Aggregate( true, ( info, item ) => { if (info == true && item > -1) { return true; } return false; }, x => x); var secondInts = Enumerable.Range(12, 3); var concat1 = ints.Concat( secondInts ); var concat2 = secondInts.Aggregate( new List<int>( ints ), ( list, i )=> { list.Add( i ); return list; }, list => list );Ok, to teraz bardziej statystyczne funkcje.
var range1 = ints.Max() - ints.Min(); var range2 = ints.Aggregate( new { Max = ints.First(), Min = ints.First() }, ( x_range, item ) =>{ var max = x_range.Max; var min = x_range.Min; if (max < item) max = item; if (min > item) min = item; return new {Max = max, Min = min}; }, x_range => x_range.Max - x_range.Min); var intsRepeatable = ints.Concat( new List<int> { 1, 2, 2, 5, 6 } ); var mode1 = intsRepeatable .ToLookup( x => x ) .OrderByDescending( x => x.Count() ) .Select( x => x.Key ).First(); var mode2 = intsRepeatable.Aggregate( new Dictionary<int, int>(), ( dic, item ) => { if (dic.Keys.Contains( item )) dic[item]++; else dic.Add( item, 1 ); return dic; }, dic => dic.OrderByDescending( x => x.Value ) .First()) .Key;A na koniec ciekawsze smaczki, czyli średnia krocząca dla 3 okresów i odchylenie standardowe.
int movingMeanCounter = 3; var movingMean3 = ints.Aggregate( new { List = new List<List<int>>(), Counter = 0 }, ( info, item ) => { info.List.Add( new List<int>() ); for (int i = 0 ; i < movingMeanCounter && info.Counter - i >= 0 ; i++) { var vList = info.List[info.Counter - i]; vList.Add( item ); } return new { List = info.List, Counter = info.Counter + 1 }; }, x => x.List.Select( item => item.Average() )); var stdDev = ints.Aggregate( new { Mean = 0, Sum = 0, i = 0 }, ( info, item ) => { var i = info.i + 1; var delta = item - info.Mean; var mean = delta / i; var sum = info.Sum + delta * (item - mean); return new { Mean = mean, Sum = sum, i = i }; }, x => x.i < 2 ? 0 : Math.Sqrt( x.Sum / (x.i - 1) ));
Możemy wiele ciekawych rzeczy zrobić za pomocą aggregate. Gdybyś miał pomysł na zastosowanie tej metody to jestem otwarty na propozycje. Więcej o niej można poczytać tutaj.
Brak komentarzy:
Prześlij komentarz