I found there is a chunk in std, but my need is to chunk elements based on a custom function instead of a known element number,
e.g. I want to chunk a vector of string and to make sure the total string length in one chunk not greater than 2,
maybe something like this:
fn main() {
let vec = vec!["a", "bbb", "ccc", "d", "e"];
// make a new chunk if total string lengths in slice are greater than 2
let chunks: Vec<Vec<&str>> = vec
.my_chunk(...)
.collect::<Vec<_>>();
chunks[0] == ["a", "bbb"];
chunk[1] == ["ccc"]
chunk[2] == ["d", "e"]
}
i or what is the ruster way to implement this kind of function
You could write your own iterator like this, but I'm not sure it's better.
use std::mem;
struct MyChunker<I> {
iter: I,
chunk: Vec<String>,
total_size: usize,
done: bool,
}
impl<I> Iterator for MyChunker<I>
where
I: Iterator<Item = String>,
{
type Item = Vec<String>;
fn next(&mut self) -> Option<Vec<String>> {
if self.done {
return None;
}
loop {
match self.iter.next() {
Some(item) => {
self.total_size += item.len();
self.chunk.push(item);
if self.total_size > 2 {
self.total_size = 0;
return Some(mem::take(&mut self.chunk));
}
}
None if self.chunk.is_empty() => {
self.done = true;
return None;
}
None => {
self.done = true;
return Some(mem::take(&mut self.chunk));
}
}
}
}
}
Note that this uses std::mem::take, which replaces the vector with an empty vector and returns the old vector. This avoids cloning the contents of the vector.