Reputation: 712
I have a vector of input String
s and I'd like to create two vectors containing references, &str
, to those strings. Here's a simplified version of what I'm trying (the input is replaced with a simple vector initialisation):
let colours = vec!["red".to_string(), "black".to_string(), "blue".to_string()];
let mut starts_with_b = Vec::new();
let mut ends_with_e = Vec::new();
for colour in colours {
if colour.starts_with("b") {
starts_with_b.push(&*colour);
}
if colour.ends_with("e") {
ends_with_e.push(&*colour);
}
}
println!("{:?}", starts_with_b);
println!("{:?}", ends_with_e);
This code produces the compiler error "'colour' does not live long enough". How can I resolve this problem?
I've seen that this problem does not exist if I start off with string references, &str
:
let colours = vec!["red", "black", "blue"];
let mut starts_with_b = Vec::new();
let mut ends_with_e = Vec::new();
for colour in colours {
if colour.starts_with("b") {
starts_with_b.push(colour);
}
if colour.ends_with("e") {
ends_with_e.push(colour);
}
}
println!("{:?}", starts_with_b);
println!("{:?}", ends_with_e);
Upvotes: 3
Views: 116
Reputation: 11708
The problem with your code comes from the fact the temporary colour
variable is a moved String
, which means it's very short-lived. In your starts_with_b
and ends_with_e
vectors you need to store references to the values in colours
, which can easily be done by simply not moving the values in colours
while iterating them. The easiest way to do that is by doing this:
for colour in &colours {
instead of this:
for colour in colours {
That way colour
will be of type &String
, instead of a (moved) String
, so you can simply push colour
directly.
Note that that way the types of starts_with_b
and ends_with_e
will be Vec<&String>
and not Vec<&str>
, as you asked for. I presume that won't be an issue for you, but if it is, you can easily make them Vec<&str>
by simply calling push(&colour[..])
instead of push(colour)
.
Upvotes: 5
Reputation: 5190
You can use for
loop on the reference of colours
:
let colours = vec!["red".to_string(), "black".to_string(), "blue".to_string()];
let mut starts_with_b = Vec::new();
let mut ends_with_e = Vec::new();
for colour in &colours {
if colour.starts_with("b") {
starts_with_b.push(colour);
}
if colour.ends_with("e") {
ends_with_e.push(colour);
}
}
println!("{:?}", starts_with_b);
println!("{:?}", ends_with_e);
Upvotes: 1