I want to iterate through a vector, and get a mutable reference to each item, and a mutable slice to the rest of the vector, so I can use both every iteration. Something like:
e.g:
for index in 0..model.len() {
let (item, rest): (&mut Item, &mut [Item]) = model.split_rest_mut(index);
item.do_something(rest);
}
e.g [1,2,3,4,5,6].split_rest_mut(2) would be 3, [1,2,4,5,6].
I would like this to be as performant as possible.
It seems to be similar behaviour to split_at_mut, so I imagine this should be possible.
How would I go about doing this?
>Solution :
With the exact signature split_rest_mut(usize) -> (&mut T, &[T]), that is impossible: for an index which is neither for the first element nor the last element, the remaining elements are not contiguous in memory, and so cannot coexist in a single slice.
Instead, such a function would have to return two slices: one for the leading part of the slice and another one for the trailing part.
+-------------+-------------+--------------+
| ...leading | middle item | ...trailing |
+-------------+-------------+--------------+
Its implementation can be built with a combination of split_at_mut and split_first_mut.
pub fn split_at_rest_mut<T>(x: &mut [T], index: usize) -> (&mut T, &mut [T], &mut [T]) {
assert!(index < x.len());
// split in two
let (leading, trailing) = x.split_at_mut(index);
// split second half in [value, ...rest]
let (val, trailing) = trailing.split_first_mut().unwrap();
(val, leading, trailing)
}
Using:
let mut v = vec![1, 2, 5, 7, 8, 9];
assert_eq!(
split_at_rest_mut(&mut v, 2),
(&mut 5, &mut [1, 2][..], &mut [7, 8, 9][..]),
);