-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Add new iterator adapator .filter_scan() #14425
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
Conversation
filter_scan() is like scan() but it skips None values. It also has a method .chain_state() that adds one final iteration value by mapping the state through a closure.
How is this different than The extra value added can't be expressed today, but why was it added for just one iterator and no others? |
@alexcrichton I added
|
As for Another option is to build a separate iterator adaptor that chains a single result by executing a closure on a |
There's a lot of similarity with this approach and my |
Closing due to inactivity, but feel free to reopen again. |
@alexcrichton I still think this is useful. All it's waiting on is a review and/or a comparison with @erickt's FWIW, |
AFAICS you can almost solve your code example using scan and filtermap, but I didn't manage to get the last word, and I don't know how well this will be optimized. fn main() {
let s = "this is a sentence";
let mut it = s.char_indices().scan(0u, |i1, (i2, c)| {
if c.is_whitespace() {
let word = s.slice(*i1, i2);
*i1 = i2+1;
Some(Some(word))
} else {
Some(None)
}
}).filter_map(|x| x);
assert_eq!(it.next(), Some("this"));
assert_eq!(it.next(), Some("is"));
assert_eq!(it.next(), Some("a"));
// assert_eq!(it.next(), Some("sentence")); # NOT WORKING
assert_eq!(it.next(), None);
} Perhaps chain_state could be renamed to finally and added as a method to the normal ScanIterator. Then the code example could be changed into something like the following let mut it = s.char_indices()
.scan(0u, |i1, (i2, c)| {
.... // Same code as above
})
// last word
.finally(|i1, (i2, _)| Some(Some( s.slice(*i1, i2+1))))
.filter_map(|x| x); Alternatively you can add a whitespace at the end of the string, but that feels like a hack. EDIT: Ideally a Peekable iterator should allow you to peek ahead inside a for-loop. That would would solve the problem of getting the last word. Perhaps i2 could have a method named peek(), but also coerce to uint. |
Closing. Between this PR and #14271, this subject has been closed several times with little agreement. Please agree on a design and convince others that it is needed. |
filter_scan() is like scan() but it skips None values. It also has a
method .chain_state() that adds one final iteration value by mapping the
state through a closure.