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