Как правильно убрать переменную и сделать код чище ?
Мне кажется BehaviorSubject то что нужно, но не получилось с ним.
using System;
using System.Linq;
using System.Reactive.Linq;
class Event { public Event(string a, int b) { A = a; B = b; } public readonly string A; public readonly int B; public override string ToString() { return A + " " + B; } }
public class Program
{
public static void Main()
{
var events = Observable.Range(1, 10).Select(i => new Event("Regular", i));
var old = 0;
var generatedEvents = events
.Where(e => e.B % 2 == 0)
.Select(e => {
var ret = new Event("Generated, Old=" + old, e.B * 3);
old = e.B; // Set oldreturn ret;
});
var allEvents = events.Merge(generatedEvents);
allEvents.Subscribe(Console.WriteLine);
}
}
Здравствуйте, _NN_, Вы писали:
_NN>Как правильно убрать переменную и сделать код чище ? _NN>Мне кажется BehaviorSubject то что нужно, но не получилось с ним.
В вашем случае можно использовать Scan:
var generatedEvents = events
.Where(e => e.B % 2 == 0)
.Scan(new { old = 0, e = default(Event) }, (ac, e) => {
var ret = new Event("Generated, Old=" + ac.old, e.B * 3);
return new { old = e.B, e = ret };
})
.Select(e => e.e);
или
var generatedEvents = Observable.Range(1, 10)
.Scan(new {old = 0, e = 0, hit = false}, (ac, e) => e % 2 == 0 ? new {old = e, e, hit = true} :new {ac.old, e, hit = false})
.SelectMany(ac => ac.hit ? new[] { new Event("Regular", ac.e), new Event("Generated, Old=" + ac.old, ac.e*3) } : new[] {new Event("Regular", ac.e)});
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Здравствуйте, _NN_, Вы писали:
_NN>А почему тогда использовать Scan ,а не Buffer в этом случае ?
И так и так можно. Scan для пары значенэий очевидней, Buffer понавороченней.
Вот есть два варианта решения, какой будет лучше и почему ?
1. Scan
public static IObservable<TResult> SelectWithPrevious<TSource, TResult>(
this IObservable<TSource> source,
Func<TSource, TSource, TResult> selector,
TSource startingCurrent)
{
if (source == null) throw new ArgumentNullException("source");
if (selector == null) throw new ArgumentNullException("selector");
return source
.Scan(
new { Current = startingCurrent, Previous = default(TSource) },
(previous, current) => new { Current = current, Previous = previous.Current })
.Select(
previousAndCurrent =>
selector(previousAndCurrent.Current, previousAndCurrent.Previous));
}
2. Переменная
public static IObservable<TResult> SelectWithPrevious<TSource, TResult>(
this IObservable<TSource> source,
Func<TSource, TSource, TResult> selector,
TSource startingCurrent)
{
if (source == null) throw new ArgumentNullException("source");
if (selector == null) throw new ArgumentNullException("selector");
var current = startingCurrent;
return source
.Select(
e =>
{
var previous = current;
current = e;
return selector(current, previous);
});
Здравствуйте, _NN_, Вы писали:
_NN>Вот есть два варианта решения, какой будет лучше и почему ?
Первый, т.к. он гарантированно останется работоспособным, если в Rx поменяется соглашение по OnNext.
previousAndCurrent структурой только сделать, чтоб аллокаций лишних не городить на каждое событие.
Здравствуйте, Sinix, Вы писали:
S>Здравствуйте, ionoy, Вы писали:
I>>А чем Buffer не угодил? S>
S>И так и так можно. Scan для пары значенэий очевидней, Buffer понавороченней.
S>^)
Я бы сказал наоборот. Буфер предназначен именно для задач, когда нужно обрабатывать несколько последних значений. Скан — значительно более универсальный инструмент, а потому его использование не такое очевидное.