Home > Blockchain >  Rust equivalent for a Javascript map over a 2D vector iterator
Rust equivalent for a Javascript map over a 2D vector iterator

Time:03-25

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.

  • Related