Reputation: 3071
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);
}
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
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