I am new to Rust. I am learning, by trying to port the code shown in Javascript (in https://youtu.be/oBt53YbR9Kk) to Rust. While trying to code the function shown at around https://youtu.be/oBt53YbR9Kk?t=10912 starting with the for-loop on line 4, I am stuck with Rust as follows.
In Javascript on line 8, we have:
const targetWays = suffixWays.map(way => [word, ...way])
In Rust, I am trying to write this as:
let target_ways = suffix_ways.into_iter().map(|way| way.insert(0, word_bank[i].clone())).collect::<Vec<Vec<String>>>();
However, I get a compile time error
value of type `std::vec::Vec<std::vec::Vec<std::string::String>>` cannot be built from `std::iter::Iterator<Item=()>`
What am I doing wrong?
CodePudding user response:
Vec::insert
returns ()
, because it simply modifies the vec in place. So the closure: |way| way.insert(0, word_bank[i].clone())
has the type fn(Vec<String>) -> ()
.
Instead, you probably want something like this:
let target_ways: Vec<_> = suffix_ways.into_iter().map(|way| {
way.insert(0, word_bank[i].clone());
way
}).collect();
FWIW, inserting to the start of a Vec
can be quite costly, since it reallocates the underlying memory and copies all the elements over. It's generally cheaper to push to the end of a vec, and reverse at the end if you have to. This is especially true you know the size of the vec in advance (and so can create it with Vec::with_capacity
to allocate all the memory in one go ahead of time).
Though if you're just learning, feel free to ignore this and just get on with building something cool :)
CodePudding user response:
For completeness, taking into account the fact that the closure must return some value and without using VecDeque
, here is the code for the function.
fn all_construct(target: String, word_bank: &mut Vec<String>) -> Vec<Vec<String>> {
if target.is_empty() {
return vec![vec![]];
}
let mut result:Vec<Vec<String>> = Vec::new();
for i in 0..word_bank.len() {
let search = &word_bank[i];
if target.starts_with(search) {
let suffix = target.chars().skip(search.len()).collect();
let mut suffix_ways = all_construct(suffix, word_bank);
let target_ways:Vec<_> = suffix_ways.iter_mut().map(|way| {
way.insert(0, word_bank[i].clone());
way.clone()
}).collect::<Vec<Vec<String>>>();
result.extend(target_ways);
}
}
result
}
Feel free to suggest improvements.