La solution consiste à maintenir en dessous de l'état des données d'événements pertinents dans les dix dernières minutes dans une liste à l'aide Observable.Scan
. L'état est maintenu sous la forme d'une liste de tuples avec un int
(argent) et un DateTime
comme valeurs.
var events = Observable.FromEvent<YourEventArgs>(
h => SomeEvent += h, h => SomeEvent -= h);
var runningSums =
events.Scan(new List<Tuple<int, DateTime>>(),
(l, e) =>
{
var now = DateTime.Now;
// Add last event data to list.
l.Add(Tuple.Create(e.EventArgs.Money, now));
// Return the correct part of the list (everything
// from the last ten minutes).
return l.Where(t => (now - t.Item2) <
TimeSpan.FromMinutes(10)).ToList();
})
.Select(l => l.Sum(t => t.Item1));
runningSums.Subscribe(sum => Console.WriteLine(sum));
EDIT: Exemple qui ne renvoie pas une nouvelle liste pour chaque événement:
var events = Observable.FromEvent<YourEventArgs>(
h => SomeEvent += h, h => SomeEvent -= h);
var runningSums =
events.Scan(Tuple.Create(new List<Tuple<int, DateTime>>(),
DateTime.Now - TimeSpan.FromMinutes(10)),
(l, e) =>
{
var now = DateTime.Now;
l.Item1.Add(Tuple.Create(e.EventArgs.Nr, now));
// if (trimming-condition) then trim front of list...
return Tuple.Create(l.Item1, now - TimeSpan.FromMinutes(10));
})
.Select(l => l.Item1.Where(t => t.Item2 > l.Item2).Sum(t => t.Item1));
runningSums.Subscribe(sum => Console.WriteLine(sum));
pas mal pour vous et fait ce qu'il faut. MAIS vous pourriez vouloir vérifier si c'est vraiment une bonne idée de retourner une nouvelle liste avec CHAQUE nouvel élément traité. – pointernil
Je ne suis pas entièrement satisfait de cela aussi. Mais, vous devez avoir une liste de valeurs avec horodatage pour pouvoir le faire. Et malgré la liste mutable, c'est une approche entièrement fonctionnelle. Ce que vous pouvez également faire est de ne pas créer une nouvelle liste à chaque fois mais de conserver la même liste et de faire en sorte que l'heure de début (toujours 10 minutes dans le passé) fasse partie de l'état de la méthode 'Scan'. Cependant, maintenant la liste ne cesse de grandir et vous devrez trouver un moyen de réduire le front. J'ai ajouté un exemple pour ceci aussi (sans le rognage, mais ceci peut être facilement ajouté). –