简洁地初始化字符串向量

Nic*_*lin 9 rust

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

我想要的是:

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

这显然不起作用,因为向量内容都是&strs.

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

let args = vec![String::from("-w"), String::from("60"), String::from("args")];
Run Code Online (Sandbox Code Playgroud)

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

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

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

JDe*_*ler 12

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

let test_args = vec!["-w".to_string(), "60".to_string(), "arg".to_string()];
Run Code Online (Sandbox Code Playgroud)

否则,执行此操作的宏将如下所示:

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

请参阅play.rust.org示例


Luk*_*odt 8

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

首先,您也可以使用into()而不是to_string()所有元素,而不是第一个.这稍微短一些,也等于to_string()/ String::from().看起来像这样:

vec!["a".to_string(), "b".into(), "c".into()];
Run Code Online (Sandbox Code Playgroud)

其次,您可能想重新设计arg解析.我会在这里假设你不会改变String你得到的env::args().我想你当前的功能看起来像:

fn parse_args(args: &[String]) -> SomeResult { ... }
Run Code Online (Sandbox Code Playgroud)

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

fn parse_args<T: AsRef<str>>(args: &[T]) -> SomeResult { ... }
Run Code Online (Sandbox Code Playgroud)

在文档中,您可以看到它String以及它str自身实现该特征.因此,您可以将a &[String] a 传递给&[&str]您的函数.太棒了,是吗?


以类似的方式,如果你想接受任何可以转换为拥有的东西String,你可以接受<T: Into<String>>,如果你想要返回a String或an &str,你可以使用Cow.您可以在这里这里阅读更多相关信息.

除了一切:有很多很好的CLI-精氨酸的解析器那里(clap-rs,docopt-rs,...),所以你可能不需要自己编写.


She*_*ter 8

我同意Lukas Kalbertodt 的答案是最好的——使用泛型来接受任何看起来像一段字符串的东西。

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

  1. 无需为初始字符串集分配向量。
  2. 没有必要使用完整的类型 ( Vec<String>);您可以仅指定集合 ( Vec<_>)。如果将结果传递给只接受 a 的函数Vec<String>,则根本不需要任何显式类型;完全可以推断出来。
  3. 您可以s.into()map.

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);
}
Run Code Online (Sandbox Code Playgroud)