let current_status: Vec<&str> = vec!["happy", "excited","glad"];
And need to change it to:
let status_reg: Vec<&str> = vec!["r\"happy\"i", "r\"excited\"i", "r\"glad\"i"];
i.e. I need to change each element value with this format
format!("r\"{}\"i", status);
I tried the below:
let mut status_reg: Vec<&str> = vec![Default::default()];
for status in rcurrent_status {
status_reg.push(format!("r\"{}\"i", status).as_str());
}
But got the below error:
status_reg.push(format!("r\"{}\"i", status).as_str());
^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
status_reg.push(format!("r\"{}\"i", status).as_str());
^ temporary value is freed at the end of this statement
status_reg.push(format!("r\"{}\"i", status).as_str());
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that borrow lasts for `'static`
temporary value dropped while borrowed
Think about the type &str in both of the Vecs. The & means that it's a reference.
In current_status, the references are to strs that are compiled into your executable, but to where do the references in rcurrent_status point? The answer is that the references point to heap-allocated Strings. But those strings get dropped too soon:
let mut status_reg: Vec<&str> = vec![Default::default()];
for status in rcurrent_status {
status_reg.push({
let heap_allocated: String = format!("r\"{}\"i", status);
let str_reference: &str = heap_allocated.as_str();
str_reference
// heap_allocated dropped here. What would str_reference point to?
});
}
The solution is to make a vector of heap-allocated Strings as vitalyd suggests. If needed, you can then make a vector that references the vector of heap-allocated Strings.
let set = RegexSet::new(&status_reg).unwrap();
let mut file = Docx::open(&path).expect("Cannot open file");
let mut isi = String::new();
let _ = file.read_to_string(&mut isi);
let matches: Vec<_> = set.matches(&isi).into_iter().collect();
let exact_matches = matches.iter().
map(|s| status_reg[*s]).collect::<Vec<&str>>();
and having String will case:
|
44 | map(|s| status_reg[*s]).collect::<Vec<_>>();
| ^^^^^^^^^^^^^^ move occurs because value has type `std::string::String`, which does not implement the `Copy` trait
RegexSet::new can work off any iterator whose elements are AsRef<str>; a Vec<String> or &[String] fits that bill. So if status_reg is a Vec<String>, RegexSet::new(&status_reg) should work. Or did I misunderstand the problem?
use std::io::Read;
use dotext::*;
use regex::RegexSet;
fn main(){
let required_skills: Vec<&str> = vec![
"Project(s|^s)", // (s|^s) ending with or without `s`
"Plicy|Policies", // either singular or plural
]; // to be scanned in the given CV
let searches =required_skills.iter().map(|s| *s).
collect::<Vec<&str>>();
// I need to replace the above by the below?!
// let searches =required_skills.iter().map(|s| format!("r\"{}\"i", s)).
// collect::<Vec<_>>();
// So based on your answer, I re-wrote it as:
// let skills_regex =required_skills.iter().map(|s| format!("r\"{}\"i", s)).
// collect::<Vec<_>>();
// let searches = skills_regex.iter().map(|s| *s).
// collect::<Vec<&str>>();
let set = RegexSet::new(&searches).unwrap();
let mut file = Docx::open("CV.docx").expect("Cannot open file");
let mut isi = String::new();
let _ = file.read_to_string(&mut isi);
if set.is_match(&isi){
let matches = set.matches(&isi).into_iter().collect::<Vec<_>>();
let exact_matches = matches.iter().
map(|s| searches[*s]).collect::<Vec<&str>>();
println!("Out of {} requirements, the below {} matches had been found:",
set.len(), matches.len());
for x in exact_matches {
println!("{}", x );
}
} else {
println!("No matches found");
}
}
In the “rewrite”, you don’t need searches - just use skills_regex. That’ll be a Vec<String>. As long as you keep it alive longer than your loop, which you do, you should be able to look things up in it by index and get a &str to an element.
let searches =required_skills.iter().map(|s| format!("r\"{}\"i", s)).
collect::<Vec<_>>();
If I wrote:
let exact_matches = matches.iter().map(|s| searches[*s]).collect::<Vec<_>>();
I get
--> src/main.rs:40:45
|
40 | map(|s| searches[s]).collect::<Vec<_>>();
| ^^^^^^^^^^^ slice indices are of type `usize` or ranges of `usize`
|
= help: the trait `std::slice::SliceIndex<[std::string::String]>` is not implemented for `&usize`
If I wrote:
let exact_matches = matches.iter().map(|s| searches[&s]).collect::<Vec<_>>();
I get
--> src/main.rs:40:45
|
40 | map(|s| searches[&s]).collect::<Vec<_>>();
| ^^^^^^^^^^^^ slice indices are of type `usize` or ranges of `usize`
|
= help: the trait `std::slice::SliceIndex<[std::string::String]>` is not implemented for `&&usize`
= note: required because of the requirements on the impl of `std::ops::Index<&&usize>` for `std::vec::Vec<std::string::String>`
If I wrote:
let exact_matches = matches.iter().map(|s| searches[s]).collect::<Vec<_>>();
I get
--> src/main.rs:40:45
|
40 | map(|s| searches[s]).collect::<Vec<_>>();
| ^^^^^^^^^^^ slice indices are of type usize or ranges of usize
|
= help: the trait std::slice::SliceIndex<[std::string::String]> is not implemented for &usize
= note: required because of the requirements on the impl of std::ops::Index<&usize> for std::vec::Vec<std::string::String>
error[E0614]: type `usize` cannot be dereferenced
--> src/main.rs:42:62
|
42 | let exact_matches = matches.iter().map(|&s| searches[*s]).collect::<Vec<_>>();
| ^^
error: aborting due to previous error
error[E0507]: cannot move out of index of `std::vec::Vec<std::string::String>`
--> src/main.rs:43:61
|
43 | let exact_matches = matches.iter().cloned().map(|s| searches[s]).collect::<Vec<_>>();
| ^^^^^^^^^^^ move occurs because value has type `std::string::String`, which does not implement the `Copy` trait
error: aborting due to previous error
Here's a working example with minimal changes (playground):
use std::io::Read;
use regex::RegexSet;
fn main(){
let required_skills: Vec<&str> = vec![
"Project(s|^s)", // (s|^s) ending with or without `s`
"Plicy|Policies", // either singular or plural
]; // to be scanned in the given CV
let searches =required_skills.iter().map(|s| format!("r\"{}\"i", s)).
collect::<Vec<String>>();
let set = RegexSet::new(&searches).unwrap();
let mut file = std::fs::File::open("CV.docx").expect("Cannot open file");
let mut isi = String::new();
let _ = file.read_to_string(&mut isi);
if set.is_match(&isi){
let matches = set.matches(&isi).into_iter().collect::<Vec<_>>();
let exact_matches = matches.iter().
map(|s| searches[*s].as_str()).collect::<Vec<_>>();
println!("Out of {} requirements, the below {} matches had been found:",
set.len(), matches.len());
for x in exact_matches {
println!("{}", x );
}
} else {
println!("No matches found");
}
}
(Note: I changed Docx::open to File::open just to make it compile on the playground.)