34

I want to split a string and return Vec<String> from my function. It has to be Vec<String> and not Vec<&str> because I can't return Vec<&str>, can I? If I can, though, how can I do that?

let var1: Vec<&str> = my_string.split("something").collect();
let res = var1.iter().map(|x| x.to_string());
// I want to return Vec<String>

I've tried different versions but gotten error: mismatched types and other kinds of similar errors. Is there an easier way?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
  • 2
    Can you please try to produce a [MCVE](http://stackoverflow.com/help/mcve) which reproduces your issue? You can use the [Playground](https://play.rust-lang.org/) to share it afterward. – Matthieu M. May 31 '16 at 13:39
  • Could you add 'string vector split' to your tags? I wasn't able to find your question, until I asked myself and got flagged for it. – Folaht Jun 08 '20 at 17:40

2 Answers2

53

You don't need to create an intermediate Vec<&str>, just map to_string() and use collect() after that:

let res: Vec<String> = my_string.split("something").map(|s| s.to_string()).collect();
Vladimir Matveev
  • 120,085
  • 34
  • 287
  • 296
  • 2
    It's even nicer when in a function, as the function return type means you don't need the `let res: Vec = ` aspect. – Shepmaster May 31 '16 at 14:06
  • 9
    You can even shorten this by replacing `.map(|s| s.to_string())` with `map(str::to_string)`. – TheOperator Dec 08 '19 at 16:38
  • 1
    I've seen `map(ToString::to_string)` as a solution as well. I don't know if that's better than `map(str::to_string)` – Folaht Jun 08 '20 at 17:45
4

You can map each &str to String an collect the result using Vec::from_iter:

use std::iter::FromIterator;

let res = Vec::from_iter(my_string.split("something").map(String::from));

This question is the opposite of this one.

Note that collect is implemented in terms of from_iter.

Community
  • 1
  • 1
malbarbo
  • 10,717
  • 1
  • 42
  • 57
  • 2
    I would like to note that using `collect()` to create a collection out of an iterator is more idiomatic than using `from_iter()` directly, but of course this is not a hard rule. Also it looks like that with the introduction of specialization `to_string()` is also the idiomatic way to convert `&str` to `String`, though I personally like `String::from` or `.into()` more. – Vladimir Matveev May 31 '16 at 14:07
  • @VladimirMatveev Thanks for the comments. You are right, [`FromIterator`](https://doc.rust-lang.org/stable/std/iter/trait.FromIterator.html) docs says that `from_iter` is rarely called explicitly, and points to `collect`. But in some cases, like in a variable definition, the `from_iter` is more readable. When the type of `collect` can be inferred, like in a function return, `collect` is more readable. – malbarbo May 31 '16 at 14:15