2016-07-04 54 views
3

我試圖創建一個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秒。

使用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>>(); 

我應該只是創建一個幫助函數來完成轉換,還是有更簡單的方法?

回答

4

您可以在文字直接使用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

感謝您的宏,這是相當不錯的!雖然'to_string'比'String :: From'略短,但是在'String :: from'上使用它有什麼好處? –

+0

它實際上是等價的:看看'to_string'的實現https://doc.rust-lang.org/src/collections/up/src/libcollections/string.rs.html#1768-1774 – JDemler

4

JDemler已經提供了很好的答案。我還有兩件事要說:

首先,您也可以使用into()而不是to_string(),而不是第一個元素。這略短,也相當於to_string()/String::from()。看起來是這樣的:

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

其次,你可能要重新設計你的ARG解析。我將在這裏假設你不會改變從env::args()得到的String。我想,你當前的功能看起來像:

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

但是你可以使功能更通用的不接受String秒,但AsRef<str>。它應該是這樣的:

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

在文檔中,你可以看到,String以及str本身實現該特性。因此,您可以將&[String] a &[&str]傳遞到您的函數中。真棒,呃?


以類似的方式,如果你想接受任何可以被轉換成一個擁有String,可以接受<T: Into<String>>,如果你想返回一個String&str,您可以使用Cow。你可以閱讀更多關於herehere。除了所有這些:CLI-Arg中有很多好的解析器(clap-rsdocopt-rs,...),所以你可能不需要編寫自己的。

4

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

但是,您可以清理map版本一點點:

  1. 沒有必要分配一個矢量初始字符串集。
  2. 有沒有必要使用完整的類型(Vec<String>);您可以只指定集合(Vec<_>)。如果將結果傳遞給僅接受Vec<String>的函數,則根本不需要任何顯式類型;它可以被完全推斷。
  3. 您可以在map中稍微縮短s.into()

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); 
}