Reputation: 16589
Is it possible to create a slice of an array (or anything else) using references into that array to specify the start/end rather than indices?
For example, say I am iterating through an array, and when I get to a certain element I want to call a function passing a slice of the array from the current element to the end:
let list = [1, 2, 3, 4, 5, 6];
for item in &list {
if passes_test(item) {
process_remainder(&list[item..]); // does not compile
}
}
Coming from C this seems like a natural thing to want to do - a reference is just a pointer, and a slice is just a pair of pointers (or pointer and length), and taking multiple references should be fine since none of them are mutable. But I can't find right syntax to do it.
Alternately, is it possible to get the index for a given reference (like with pointer arithmetic in C), or do I just need to break down and use enumerate to generate both index and reference as I iterate?
Upvotes: 3
Views: 669
Reputation: 182063
You can do it, but it's neither safe nor pretty:
let list = [1, 2, 3, 4, 5, 6];
for item in &list {
if passes_test(item) {
let idx = unsafe { (item as *const u64).offset_from(list.as_ptr()) as usize };
process_remainder(&list[idx..]);
}
}
Using enumerate
is a better option:
let list = [1, 2, 3, 4, 5, 6];
for (i, item) in list.iter().enumerate() {
if passes_test(item) {
process_remainder(&list[i..]);
}
}
Upvotes: 3
Reputation: 6614
Usually, enumerate
is preferred over pointer arithmetic.
fn main() {
let list = [1i32, 2, 3, 4, 5, 6];
for (index, item) in list.iter().enumerate() {
if *item > 5 {
process_remainder(&list[index..]);
}
}
}
(Accidentally, your code does compile since array items are usize
. :) So I changed them to i32
.)
Upvotes: 4