You can write your function like this:
fn take<T>(mut vec: Vec<T>, index: usize) -> Option<T> {
if vec.get(index).is_none() {
None
} else {
Some(vec.swap_remove(index))
}
}
The code you see here (get
and swap_remove
) is guaranteed O(1).
However, kind of hidden, vec
is dropped at the end of the function and this drop operation is likely not O(1), but O(n) (where n is vec.len()
). If T
implements Drop
, then drop()
is called for every element still inside the vector, meaning dropping the vector is guaranteed O(n). If T
does not implement Drop
, then the Vec
only needs to deallocate the memory. The time complexity of the dealloc
operation depends on the allocator and is not specified, so we cannot assume it is O(1).
To mention another solution using iterators:
fn take<T>(vec: Vec<T>, index: usize) -> Option<T> {
vec.into_iter().nth(index)
}
While Iterator::nth()
usually is a linear time operation, the iterator over a vector overrides this method to make it a O(1) operation. Of course, if T
implements Drop
, this again is an O(n) function as n elements need to be dropped.