【问题标题】:Select n last elements before some condition is met在满足某些条件之前选择最后 n 个元素
【发布时间】:2019-01-08 16:52:17
【问题描述】:

是否有任何专用的交互式扩展方法可以在遇到某些条件之前生成最后 n 个元素?

例如对于数组src,我想在它之前获取元素 99 加上 2 个元素:

var src = new[] { 1, 2, 3, 4, 99, 5, 6, 7, 99, 8, 9, 10, 99 };

{{3, 4, 99}, {6, 7, 99}, {9, 10, 99}}

我想出了以下代码,但想知道是否有专用方法或方法组合来执行此操作。

var result = src.Buffer(3, 1).Where(i => i.Count == 3 && i.Last() == 99);

【问题讨论】:

  • 我认为这与您将获得的一样好。您对现有解决方案有疑问吗?
  • 我只是想确保我以正确的方式进行操作。我最终编写了一个扩展方法,它结合了BufferWhere 运算符。

标签: c# system.interactive


【解决方案1】:

所以,我也对其他解决方案很好奇,并决定尝试一下。我确实想出了一个使用窗口的不同解决方案:

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 }

但是窗口化解决方案将 observables 交错(这是有道理的):

{ 3, 4, 4, 99, 99, 99, 6, 7, 99, 9, 10, 99 }

使用Buffer 解决方案时要考虑的一件事是,每个缓冲区都需要在返回之前将缓冲区复制到新列表中。因此,在某些情况下,窗口解决方案可能会表现得更好。我承认我不了解 observables 的内部工作原理以及我对 enumerables 的了解,因此我必须进行一些测试才能确定。

无论如何,玩起来很有趣,根据您的最终目标,它可能是一个可行的解决方案。

【讨论】:

  • 为尝试某件事点赞。有趣的结果。不过,我可能仍会坚持使用简单的缓冲区 :)
猜你喜欢
  • 2021-10-17
  • 2014-07-17
  • 2013-04-13
  • 2015-05-21
  • 1970-01-01
  • 2014-07-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多