Here is my use case, I want to achieve things like some_string.chars().rev().scan().rev()
But this is impossible because scan()
doesn't return DoubleEndedIterator.
My solution would be like that at present:
let mut b: Vec<_> = s.chars().rev().scan(1, cmp).collect();
b.drain(..).rev();
I also tried this:
let mut b: Vec<_> = s.chars().rev().scan(1, cmp).collect(); // <- clippy #[warn(clippy::needless_collect)]
b.into_iter().rev();
Clippy suggests me to write the wrong one:
s.chars().rev().scan(1, cmp).rev();
I wonder what's the best way to avoid this collection cost?
my version info:
rustup 1.24.3 (ce5817a94 2021-05-31)
info: This is the version for the rustup toolchain manager, not the rustc compiler.
info: The currently active `rustc` version is `rustc 1.56.0 (09c42c458 2021-10-18)`
If you are interested, I can show you why I need this feature, in the following.
I was working on a leetcode problem Shortest Distance to a Character - LeetCode
Originally I wrote code like this:
impl Solution {
pub fn shortest_to_char(s: String, c: char) -> Vec<i32> {
let cmp = |dist: &mut i32, e: char| {
if e == c {
*dist = 0;
} else {
*dist += 1;
}
Some(*dist)
};
s.chars()
.scan(s.len() as i32, cmp)
.zip(s.chars().rev().scan(s.len() as i32, cmp).rev())
.map(|e| e.0.min(e.1))
.collect()
}
}
this code is tricky but also very funny, I avoid use index variables to iterate the string twice and I even reused the closure.
But saddly it won't compile. As talked previously, I changed my code as blow and it is accepted by Leetcode.
impl Solution {
pub fn shortest_to_char(s: String, c: char) -> Vec<i32> {
let cmp = |dist: &mut i32, e: char| {
if e == c {
*dist = 0;
} else {
*dist += 1;
}
Some(*dist)
};
let mut b: Vec<_> = s.chars().rev().scan(s.len() as i32, cmp).collect();
s.chars()
.scan(s.len() as i32, cmp)
.zip(b.drain(..).rev())
.map(|e| e.0.min(e.1))
.collect()
}
}
Can I write a better one avoiding collect the vectore b
?