Ho creato un operatore SlidingWindow() per estensioni reattive perché voglio monitorare facilmente cose come medie mobili, ecc. Come un semplice esempio, voglio iscriversi per ascoltare gli eventi del mouse, ma ogni volta c'è un evento che voglio ricevere gli ultimi tre (invece di aspettare ogni terzo evento per ricevere gli ultimi tre). Ecco perché gli overload di Window che ho trovato non sembrano darmi quello che mi serve fuori dalla scatola.Problemi nell'implementazione di una finestra scorrevole in Rx
Questo è quello che mi è venuto in mente. Temo che potrebbe non essere la soluzione più performante, date le sue frequenti operazioni List:
public static IObservable<List<T>> SlidingWindow<T>(this IObservable<T> seq, int length)
{
var seed = new List<T>();
Func<List<T>, T, List<T>> accumulator = (list, arg2) =>
{
list.Add(arg2);
if (list.Count > length)
list.RemoveRange(0, (list.Count - length));
return list;
};
return seq.Scan(seed, accumulator)
.Where(list => list.Count == length);
}
Può essere chiamato in questo modo:
var rollingSequence = Observable.Range(1, 5).SlidingWindow().ToEnumerable();
Tuttavia, con mia grande sorpresa, invece di ricevere il risultati attesi
1,2,3
2,3,4
3,4,5
ricevo i risultati
2,3,4
3,4,5
3,4,5
Qualsiasi approfondimento sarebbe molto apprezzato!
@blaster Nessun problema: in effetti, grazie per "avermi fatto", lo ho scritto, poiché l'ho usato io stesso un paio di volte da quando ho risposto a questo. ;) – JerKimball
Non penso che questo sia buono. I file .Publish(), .Range (0, x) e .Skip() - quando questi sono combinati, sembrano prestazioni scadenti, in particolare O n^2, perché Skip sta andando a ripetere l'intero flusso ripetutamente.Ad esempio, è necessario iterare 30.000 interi per ottenere (10000, 10001, 10002). Quindi in realtà non stai mantenendo un buffer scorrevole del flusso sorgente in memoria, dovresti mantenere l'intero stream sorgente (dall'inizio del tempo) in memoria, che è quello che pensavo stessimo evitando. – yzorg
@yzorg controlla la modifica – JerKimball