Utworzono operator SlidingWindow() dla reaktywnych rozszerzeń, ponieważ chcę łatwo monitorować takie rzeczy, jak średnie kroczące itp. Jako prosty przykład chcę subskrybować, aby usłyszeć zdarzenia myszy, ale za każdym razem jest wydarzenie, które chcę otrzymać trzy ostatnie (zamiast czekać na co trzecie wydarzenie, aby otrzymać trzy ostatnie). Właśnie dlatego przeciążenie okna, które znalazłem nie wydaje mi się, co muszę z pudełka.Problemy z zaimplementowaniem okna przesuwnego w Rx
Oto, co wymyśliłem. Obawiam się, że może nie być najbardziej wydajnych rozwiązanie, biorąc pod uwagę jego częste operacje Lista:
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);
}
To można nazwać w ten sposób:
var rollingSequence = Observable.Range(1, 5).SlidingWindow().ToEnumerable();
Jednak, ku mojemu wielkiemu zaskoczeniu, zamiast otrzymaniu spodziewane wyniki
1,2,3
2,3,4
3,4,5
otrzymam wyniki
2,3,4
3,4,5
3,4,5
Wszelkie spostrzeżenia są mile widziane!
@blaster Bez problemu - w rzeczywistości, dziękuję za "zrobienie" mnie, że to piszę, ponieważ użyłem go sam kilka razy, od czasu odpowiedzi. ;) – JerKimball
Nie sądzę, że to jest dobre. .Publish(), .Range (0, x) i .Skip() - gdy są połączone, to wygląda na złą wydajność, konkretnie O n^2, ponieważ Skip ma zamiar iterować cały strumień w kółko.Na przykład musisz przetestować 30 000 liczb całkowitych, aby uzyskać (10000, 10001, 10002). Tak naprawdę nie przechowujesz w pamięci przesuwnego bufora strumienia źródłowego, musisz przechowywać cały strumień źródłowy (od początku czasu) w pamięci, co uważałem za unikanie. – yzorg
@yzorg sprawdź edycję – JerKimball