Why FromIterator<&String> is not implemented for Vec<String>?

Hi!
I have a code like this example:

use std::collections::HashMap;

fn main() {
    let mut dict: HashMap<String, Vec<String>> = HashMap::new();
    dict.insert("a".to_string(), vec!["a".to_string(), "aa".to_string(), "y".to_string()]);
    dict.insert("b".to_string(), vec!["b".to_string(), "battle".to_string()]);
    
    let table = vec!["a", "b"];
    
    
    let res: Vec<String> = table.iter().flat_map(|&item| {
        dict[item].iter().filter(|i| {
            i.contains("a")
        })
    }).collect();
    
    println!("{:?}", res);
}

But this doesn’t compile, as there is a required trait not implemented:

error[E0277]: a collection of type `std::vec::Vec<std::string::String>` cannot be built from an iterator over elements of type `&std::string::String`
  --> src/main.rs:15:8
   |
15 |     }).collect();
   |        ^^^^^^^ a collection of type `std::vec::Vec<std::string::String>` cannot be built from `std::iter::Iterator<Item=&std::string::String>`
   |
   = help: the trait `std::iter::FromIterator<&std::string::String>` is not implemented for `std::vec::Vec<std::string::String>`

Why this trait haven’t implemented yet? are there any reasons?

Because of the error I have to use this workaround:

    let res: Vec<String> = table.iter().flat_map(|&item| {
        dict[item].iter().filter_map(|i| {
            if i.contains("a") {
                Some(i.to_owned())
            } else {
                None
            }
        })
    }).collect();

playground link

Sorry for the noise!
Thanks! :blush:

Such an implementation would require cloning the &Strings. But at that point, you may as well request cloning yourself:

 let res: Vec<String> = table
        .iter()
         // note the cloned() at the end
        .flat_map(|&item| dict[item].iter().filter(|i| i.contains("a")).cloned())
        .collect();

You can use Rc<str> instead of String if you don’t mutate the strings and expect to clone lots of them.

1 Like

Thank you so much! I think the String’s would not be more than 15, so there’s nothing to worry, right? :wink: