因此,我也对其他解决方案感到好奇,并决定尝试一下。我确实想出了一个使用窗口的不同解决方案:
var src = new[] { 1, 2, 3, 4, 99, 5, 6, 7, 99, 8, 9, 10, 99 };
var obs = src.ToObservable().Publish().RefCount();
var windows =
obs
.Zip(
obs.Skip(2).Concat(Observable.Repeat(0, 2)),
(chase, lead) => (chase, lead))
.Publish(pub =>
pub
.Window(
pub.Where(x => x.lead == 99),
_ => pub.Skip(1)));
有了这个解决方案windows
,现在是一个IObservable<IObservale<int>>
. 大理石图看起来像这样(我希望这是有道理的,我正在讨论表示可观察对象的最佳方式):
src: 1--2--3--4--99--5--6--7--99--8--9--10--99--
WINDOW QUERY
: ------3--4--99-----------------------------
: -------------------6--7--99----------------
: --------------------------------9--10--99--
乍一看,行为看起来与您的解决方案相同,但在玩弄它之后,我意识到当您有重叠的寡妇时,它的行为完全不同。
如果您改用它src
:
// Note the adjacent 99s.
var src = new[] { 1, 2, 3, 4, 99, 99, 6, 7, 99, 8, 9, 10, 99 };
您的解决方案产生:
{{3, 4, 99}, {4,99,99}, {6, 7, 99}, {9, 10, 99}}
虽然窗口解决方案产生了这个:
src: 1--2--3--4--99--99--6--7--99--8--9--10--99--
WINDOW QUERY
: ------3--4--99-----------------------------
: ---------4--99--99-------------------------
: -------------------6--7--99----------------
: --------------------------------9--10--99--
在您调用这两个结果之前,它似乎没有什么不同。SelectMany
然后你的看起来像这样:
{ 3, 4, 99, 4, 99, 99, 6, 7, 99, 9, 10, 99 }
但是窗口解决方案将可观察对象交错(这是有道理的):
{ 3, 4, 4, 99, 99, 99, 6, 7, 99, 9, 10, 99 }
使用该解决方案时要考虑的一件事Buffer
是,每个缓冲区都需要在返回之前将缓冲区复制到新列表中。因此,在某些情况下,窗口解决方案可能会表现得更好。我承认我不了解 observables 的内部工作原理以及我对 enumerables 的了解,因此我必须进行一些测试才能确定。
无论如何,玩起来很有趣,根据您的最终目标,它可能是一个可行的解决方案。