Cysharp / R3

The new future of dotnet/reactive and UniRx.
MIT License
2.27k stars 99 forks source link

TakeUntil with a predicate? #238

Closed OpenEnergyGroup closed 3 months ago

OpenEnergyGroup commented 3 months ago

Consider a sequence of booleans e.g. [false, false, false, true] - the ideas is to keep iterating until True. Initially I thought you could TakeWhile(b => false) and then have a separate action on Completion. This works, but only if we start with false. If the sequence is [true, false, ... ] then that strategy won't work, because TakeWhile will never happen.

(I believe this has been implemented in RxJava as TakeWhilewith an optional emit-last-value parameter.)

It's quite useful I believe, and not achievable easily with the existing patterns.

Thank you.

neuecc commented 3 months ago

It's ok to add TakeWhile(predicate, bool emitLastValue) method. I'm not quite sure if your example is okay with that.

1619digital commented 3 months ago

Hi, yes TakeWhile(predicate, bool emitLastValue) is functionally equivalent to TakeUntil(inverse-predicate)

This in RxJS:

import { from, takeWhile } from 'rxjs';

var sequence = ["A", "B", "C", "D", "E", "F", "G"]

from(sequence).pipe(takeWhile(x => x !== "E")).subscribe(x => console.log(x)); // => ABCD

from(sequence).pipe(takeWhile(x => x !== "E", true)).subscribe(x => console.log(x)); // => ABCDE

from(sequence).pipe(takeWhile(x => x !== "A", true)).subscribe(x => console.log(x)); // => A

However, I suggest TakeUntil(predicate) is more understandable, and isn't hiding behind a magic flag. Also, you already have TakeUntil, and Rx.NET has it in this form too.

So in the above, much more intuitive to say TakeUntil(x => x == "E") or TakeUntil(x => x == "A")

Thanks.

neuecc commented 3 months ago

v1.2.0 added TakeUntil(predicate), thanks.