Listerone
Listerone

Reputation: 1591

How to extract elements of a vector of strings in Rust?

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

Answers (2)

Hong Jiang
Hong Jiang

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

Laney
Laney

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

Related Questions