Вот несколько вариантов, выберите один.Давайте назовем наш перечислимый e:
var e = new[]
{
"1", "5",
"Transition Good->Bad",
"3", "2",
"Transition Bad->Good",
"7",
"Transition Good->Bad",
"9", "12"
};
Если у вас есть перечислимое значение, а сигнал включения / выключения смешан, то использование .Scan () наиболее очевидно.По сути, это функциональная версия цикла foreach с изменяемым флагом:
var goods = e
.Scan(Tuple.Create("", 1),
(x, y) => Tuple.Create(y,
y.StartsWith("Transition")
? y.EndsWith("Good") ? 1 : -1
: x.Item2))
.Where(x => !x.Item1.StartsWith("Transition") && x.Item2 > 0)
.Select(x => x.Item1);
Если у вас есть перечислимый объект и вы не возражаете написать свою собственную функцию расширения специально для этого случая, то, вероятно, наиболее уместно использовать yield return:
public static IEnumerable<TSource> SplitByMarkers<TSource>(
this IEnumerable<TSource> source, Func<TSource, int> fMarker)
{
var isOn = true;
foreach (var value in source)
{
var m = fMarker(value);
if (m == 0)
if (isOn)
yield return value;
else
continue;
else
isOn = m > 0;
}
}
var goods = e.SplitByMarkers(x =>
x.StartsWith("Transition")
? x.EndsWith("Good") ? 1 : -1
: 0);
Если у вас есть наблюдаемые, и особенно если маркеры существуют как отдельные наблюдаемые, лучший вариант для создания расширения AndOn на основе .CombineLatest:
public static IObservable<TSource> AndOn<TSource>(
this IObservable<TSource> source, IObservable<bool> onOff)
{
return source
.CombineLatest(onOff, (v, on) => new { v, on })
.Where(x => x.on)
.Select(x => x.v);
}
Вы можете использоватьAndOn с перечисленным выше, как это:
var o = e.ToObservable().Publish();
var onOff = o
.Where(x => x.StartsWith("Transition"))
.Select(x => x.EndsWith("Good"))
.StartWith(true);
var goods = o
.AndOn(onOff)
.Where(x => !x.StartsWith("Transition"));
using (goods.Subscribe(Console.WriteLine))
using (o.Connect())
{
Console.ReadKey();
}
И, наконец, способ RX geek, с помощью оператора Join, доступного в выпадающем списке RX в декабре 2010 года:
var o = e.ToObservable().Publish();
var gb = o.Where(x => x == "Transition Good->Bad");
var bg = o.Where(x => x == "Transition Bad->Good").Publish("");
var goods =
from s in o
join g in bg on Observable.Empty<string>() equals gb
where !s.StartsWith("Transition")
select s;
using (goods.Subscribe(Console.WriteLine))
using (bg.Connect())
using (o.Connect())
{
Console.ReadKey();
}