Reputation: 1591
Let's say I have the following code:
fn extract() -> Vec<String> {
let data = vec!["aaa".to_string(), "bbb".to_string(), "ccc".to_string()];
vec![data[0], data[2]]
}
In practice, I read data
from a file.
Obviously, this doesn't compile because I'm pulling strings out of the vector data
, leaving the vector in an undefined state. But, conceptually, it should work, because I'm not using data
afterwards anyway.
I can use mem::replace
, but this seems crazy:
fn extract() -> Vec<String> {
let mut data = vec!["aaa".to_string(), "bbb".to_string(), "ccc".to_string()];
let a = mem::replace(&mut data[0], "".to_string());
let c = mem::replace(&mut data[2], "".to_string());
vec![a, c]
}
How do I go about extracting specific elements from the vector without having to clone the strings?
Upvotes: 4
Views: 3530
Reputation: 2376
You cannot have "holes" in a vector. So when you move something out of it, you either change the indices of the remaining elements (using remove
or swap_remove
), or replace it with something else.
Why don't you just consume the vector in order and ignore what you don't need? If you need to save some of the elements for later use, you can use data.iter().filter(...).collect()
. If you really want to avoid copying any strings, you can wrap them in Rc
so that only pointers are copied.
Upvotes: 1
Reputation: 1649
Vec
has special methods for that. swap_remove
, remove
(warning, linear complexity), drain
. For example,
fn extract() -> Vec<String> {
let mut data = vec!["aaa".to_string(), "bbb".to_string(), "ccc".to_string()];
// order does matter
vec![data.swap_remove(2), data.swap_remove(0)]
}
Upvotes: 5