I'm pretty sure you wanted to get mutable references into the original slice using the iterator, resulting in &mut [&mut 1, &mut 4, &mut 7], &mut [&mut 2, &mut 5, &mut 8], &mut [&mut 3, &mut 6, &mut 9]
.
Without allocation / unsafe / external crates. Requires rust version 1.55 or greater:
fn iter_chunks<T, const CHUNK_SIZE: usize>(
slice: &mut [T],
) -> impl Iterator<Item = [&mut T; CHUNK_SIZE]> + '_ {
assert_eq!(slice.len() % CHUNK_SIZE, 0);
let len = slice.len();
let mut a: [_; CHUNK_SIZE] = array_collect(
slice
.chunks_mut(len / CHUNK_SIZE)
.map(|iter| iter.iter_mut()),
);
(0..len / CHUNK_SIZE).map(move |_| array_collect(a.iter_mut().map(|i| i.next().unwrap())))
}
/// Builds an array from the first `N` items of an iterator
///
/// Panics:
///
/// If there are less then `N` items in the iterator
fn array_collect<T, const N: usize>(mut iter: impl Iterator<Item = T>) -> [T; N] {
let a: [(); N] = [(); N];
a.map(|_| iter.next().unwrap())
}
Without allocation, using an external crate:
We need to use arrayvec
since Rust's array cannot be used with collect
.
use arrayvec::ArrayVec;
fn main() {
let slice = &mut [1, 2, 3, 4, 5, 6, 7, 8, 9];
for (i, chunk) in iter_chunks::<_, 3>(slice).enumerate() {
println!("{:?}", chunk);
for t in chunk {
*t = i;
}
}
println!("slice: {:?}", slice);
}
fn iter_chunks<T, const CHUNK_SIZE: usize>(
slice: &mut [T],
) -> impl Iterator<Item = ArrayVec<&mut T, CHUNK_SIZE>> + '_ {
let len = slice.len();
let mut a: ArrayVec<_, CHUNK_SIZE> = slice
.chunks_mut(len / CHUNK_SIZE)
.map(|chunk| chunk.iter_mut())
.collect();
(0..len / CHUNK_SIZE).map(move |_| {
a.iter_mut()
.map(|iter| iter.next().unwrap())
.collect::<ArrayVec<_, CHUNK_SIZE>>()
})
}
Output:
[1, 4, 7]
[2, 5, 8]
[3, 6, 9]
slice: [0, 1, 2, 0, 1, 2, 0, 1, 2]