-
Notifications
You must be signed in to change notification settings - Fork 13k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Inclusive version of take_while #62208
Comments
How about a for v in h
.iter_linear(1_000)
.skip_while(|v| v.quantile() < 0.01)
.take_until(|v| v.quantile() >= 0.99) |
@Lonami |
Oh, I completely missed you mentioned |
No worries at all, happens to us all! I'd be curious to hear your thoughts on whether the |
|
How about a generic fn take_while_then<F, T, I>(self, while: F, then: T) -> TakeWhileThen<Self, F, T, I>
while
for<'a> F: FnOnce(&'a Self::Item) -> bool,
T: FnOnce(Self) -> I,
I: IntoIterator; The resulting adapter would:
The existing Although I'm not sure how useful this kind of method would be, and it may be better to just have some form of |
I also needed this recently to decode some protocol where a stop bit is used to indicate the last byte of a field. The other 7 bits are used to encode the data. I could not use the iterator API because of this. The implementation should be less or more the same as next could be implemented as: #[inline]
fn next(&mut self) -> Option<I::Item> {
if self.flag {
None
} else {
let x = self.iter.next()?;
if (self.predicate)(&x) {
self.flag = true;
}
Some(x)
}
} This would, however, take all elements until some condition is true, which is not the same as The |
I created a crate with this functionality: https://github.com/hdevalke/take-until |
Could be a good fit for the |
@michaelsproul |
I don't think If you don't mind, I'd be happy to try and get your code into |
@michaelsproul no problem if you want to do it, most of the code I wrote was inspired by the implementation of |
@hdevalke @michaelsproul Did it get into |
I'm sorry, I never got around to adding it! |
@michaelsproul That's regrettable. I opened an issue (rust-itertools/itertools#597). I got around in my project using the |
The implementation in the first post also seems to suffer from the need to take one more element from the underlying iterator when condition has been already met, which is probably fine for iterators working on data, but may become an issue for iterators that hide long operations. On a side note, is there any idiomatic way to construct |
Lambda now stores tokens of the params: - Beacuse we store the params as just a vec of strings, we can't store tokens inside each param. - Impl TokenHoarder and TokenGiver for Lambda, but these must only be used for tokens of the parameters, not the body - Impl constructor for Lambda since the `param_tokens` are private Better error display in lambda: - During creation, lambdas now store the tokens of the parameters - Shows nice error if wrong number of args are given to `lambda` the built-in function - Shows nice error if any of the params are not a symbol - Shows nice error if number of args and params mismatch - shows both Fix lambda return value bug: - When the body of a lambda had an error, it would return `false` instead of showing the error - This was because `take_while` would consume the `Result` which had error, discard it and stop taking. - when it was the only expr in the body, it would return an empty iterator which causes the default value in `unwrap_or` to be returned (which was `false`) - Replaced the take_while with a manual loop - returns the first error we see and does not consume further - keeps storing the last (not error) result - returns the last result or `false` is nothing is available - Note: this could have been written a little more elegantly using something like `take_until`: - rust-lang/rust#62208 - rust-itertools/itertools#597
Since rust doest have an inclusive "take_while" (rust-lang/rust#62208) for iterators I had to use an extra crate (https://crates.io/crates/take-until), which is something I don't particularly like as I believe crates should do something more than just adding a single thing. Oh, well, they'll add it!
Would it make sense to extend the PR to allow taking
Also, shouldn't the example initialize got_true with |
616: Add `take_while_inclusive` method r=jswrenn a=e-rhodes Adds `take_while_inclusive` method that returns elements as long as a predicate is satisfied, but including the first element that doesn't satisfy the predicate. First discussed addition to std in <rust-lang/rust#62208>. Closes #597. Co-authored-by: Erik Rhodes <erik@space-nav.com>
Iterator::take_while
stops before the first element where the condition evaluates tofalse
. That is the correct behavior given its name, but it makes it difficult to write an iterator that should include the boundary element. In particular consider something like iterating over a histogram, trimming off the tails:This may seem right, but consider an iterator where the elements are such that
v.quantile()
yields this sequence:[0, 0.02, 0.99]
. Here, the bin that spans<0.02-0.99]
will be dropped, even though it includes the majority of the samples. What we really want to do is take from the iterator until we have received an element whosev.quantile() > 0.99
. To write that withtake_while
, we need something like:Which isn't exactly obvious.
So, I propose we add
Iterator::take_until_inclusive
, which yields elements up to and including the first element for which its argument returns true. The name isn't great, but I'm also struggling to come up with a better one. In some sense, I want the function to communicate that it yields every item it evaluates. Some other possible names if we're willing to invert the boolean:break_once
,break_after
,end_at
,end_once
,end_after
.Thoughts?
The text was updated successfully, but these errors were encountered: