Выберите n последних элементов, прежде чем будет выполнено какое-либо условие - PullRequest
0 голосов
/ 08 января 2019

Существует ли какой-либо специальный метод Interactive Extensions, который будет производить последние 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);

1 Ответ

0 голосов
/ 10 января 2019

Итак, я заинтересовался другими решениями и решил поиграть с ним. Я придумал другое решение с использованием окон:

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 необходимо учитывать, что каждый буфер требует копирования буфера в новый список перед его возвратом. Таким образом, возможно, что оконное решение может работать лучше в некоторых сценариях. Я признаю, что я не понимаю внутреннюю работу наблюдаемых, так же как я делаю перечислимые, поэтому я должен был бы провести некоторое тестирование, чтобы быть уверенным.

В любом случае, было весело поиграть, и это может быть жизнеспособным решением в зависимости от вашей конечной цели.

...