user10607
user10607

Reputation: 3071

How to get Vec<&String> after using iter().filter().collect() instead of Vec<&&String>

I have a vector of Strings. I want to get two subsets from this vector: strings with "zzz" and strings with "bye".

The type of each subset is Vec< && String>. Which is a vector of references to a reference to original String. How can I get just Vec<& String>?

Code I am currently working on:

use std::string::String;
use std::vec::Vec;

fn main() {
    let a1 = String::from("hi");
    let a2 = String::from("bye");
    let a3 = String::from("zzz");

    let v_before: Vec<&String> = vec![&a1, &a2, &a3];

    // ref_a is a copy of v_before[0]
    let ref_zzz_a: &String = v_before[2];
    let ref_zzz_b: &String = v_before[2];

    println!("before: {:?}", v_before);

    // QUESTION: why can not this also be Vec<& String> ?
    // v_zzz is just like making  vec![ref_zzz_a, ref_zzz_b]
    let v_zzz: Vec<&&String> = v_before
        .iter()
        .filter(|&&element| element.contains("zzz"))
        .collect();

    let v_bye: Vec<&&String> = v_before
        .iter()
        .filter(|&&element| element.contains("bye"))
        .collect();

    let hand_made: Vec<&String> = vec![ref_zzz_a, ref_zzz_b];

    println!("v_zzz: {:?}", v_zzz);
    println!("v_bye: {:?}", v_bye);
    println!("hand_made: {:?}", hand_made);
}

(Playground)

One way would be to use vector.into_iter()..., but then I would not be able to run the second filter.

Also maybe this is just the way rust is? Due to automatic dereference maybe I should just not care that this is a Vec<&& String>? Would it lead to problems later?

Upvotes: 6

Views: 2131

Answers (1)

Peter Hall
Peter Hall

Reputation: 58735

You can use Iterator::cloned to clone each reference instead of referencing them again:

let v_zzz: Vec<&String> = v_before
    .iter()
    .filter(|&element| element.contains("zzz"))
    .cloned()
    .collect();

Cloning a reference is cheap, since it is implemented by dereferencing.


Aside: usually it's better to pass around &str instead of &String, as it's more flexible. When I see &String in Rust code, it stands out as something that is probably not intended, or can be improved.

Upvotes: 11

Related Questions