简明地初始化字符串向量

时间:2016-07-04 11:23:38

标签: rust

我正在尝试创建一个String s的向量来测试arg解析(因为这是std::env::args()返回的内容)但是如何简洁地解决这个问题。

我想要的是什么:

let test_args = vec!["-w", "60", "arg"]; // should array of Strings
let expected_results = my_arg_parser(test_args);

这显然不起作用,因为向量内容都是&str s。

使用String::from但有效但不能很好地扩展并且很难看:)

let args = vec![String::from("-w"), String::from("60"), String::from("args")];

我可以映射引用并返回字符串对象,但这看起来非常冗长:

let args = vec!["-w", "60", "args"].iter().map(|x| x.to_string()).collect::<Vec<String>>();

我应该创建一个辅助函数来进行转换,还是有更简单的方法?

3 个答案:

答案 0 :(得分:9)

您可以直接在文字上使用to_string()方法:

let test_args = vec!["-w".to_string(), "60".to_string(), "arg".to_string()];

否则执行此操作的宏将非常简单:

macro_rules! vec_of_strings {
    ($($x:expr),*) => (vec![$($x.to_string()),*]);
}

See play.rust.org example

答案 1 :(得分:6)

JDemler已经提供了一个很好的答案。我还有两件事要说:

首先,除第一个元素外,您还可以使用into()代替to_string()。这略短,也相当于to_string() / String::from()。看起来像这样:

vec!["a".to_string(), "b".into(), "c".into()];

其次,您可能想重新设计arg解析。我将在此假设您不会改变String来自env::args()的{​​{1}}。我想你当前的功能看起来像:

fn parse_args(args: &[String]) -> SomeResult { ... }

但是,您可以通过不接受String而不是AsRef<str>来使该功能更通用。它看起来像这样:

fn parse_args<T: AsRef<str>>(args: &[T]) -> SomeResult { ... }

在文档中,您可以看到String以及str本身实现了该特征。因此,您可以将&[String] &[&str]传递到您的函数中。太棒了,嗯?

以类似的方式,如果您想接受任何可以转换为拥有String的内容,您可以接受<T: Into<String>>,如果您想要返回String或{ {1}},您可以使用Cow。您可以详细了解herehere

除此之外:有很多好的CLI-Arg解析器(clap-rsdocopt-rs,...),所以你可能不需要编写自己的。

答案 2 :(得分:4)

我同意Lukas Kalbertodt's answer是最好用的泛型来接受任何看起来像一串字符串的东西。

但是,您可以稍微清理map版本:

  1. 无需为初始字符串集分配矢量。
  2. 无需使用完整类型(Vec<String>);你只能指定集合(Vec<_>)。如果将结果传递给只接受Vec<String>的函数,则根本不需要任何显式类型;它可以完全推断出来。
  3. 您可以在s.into()中使用稍短的map
  4. fn do_stuff_with_args(args: Vec<String>) { println!("{}", args.len()) }
    
    fn main() {
        let args = ["-w", "60", "args"].iter().map(|&s| s.into()).collect();
        do_stuff_with_args(args);
    }