dictionary – 作为函数参数的通用映射

我写了一个方法:

fn foo(input: HashMap<String, Vec<String>>) {...}

然后我意识到,为了编写测试,我想控制迭代顺序(可能是BTreeMap或LinkedHashMap).这导致了两个问题:

>我可以使用哪些特性或特征组合基本上表达“字符串到字符串向量的映射”?我没有在HashMap的文档中看到任何有希望的东西.
>事实证明,在这个方法中,我只想迭代映射条目,然后迭代每个字符串向量中的项目,但无法找出用于指定它的正确语法.写这个的正确方法是什么?

fn foo(input: IntoIterator<(String, IntoIterator<String>)>) {...}

最佳答案 描述抽象的HashMap没有这样的特性.我相信没有计划制作一个.到目前为止,最好的答案是你的#2建议:对于只读的HashMap,你可能只想要迭代一些东西.

要在语法级别回答,您尝试编写:

fn foo(input: IntoIterator<(String, IntoIterator<String>)>)

但这是无效的,因为IntoIterator没有模板参数:

pub trait IntoIterator where Self::IntoIter::Item == Self::Item {
    type Item;
    type IntoIter: Iterator;
    fn into_iter(self) -> Self::IntoIter;
}

然而,它需要两个相关的类型,所以你真正想表达的可能是以下内容(内部我将嵌套的IntoIterator更改为Vec的具体类型以简化):

fn foo<I>(input: I)
where I: IntoIterator<
             Item=(String, Vec<String>), 
             IntoIter=IntoIter<String, Vec<String>>>

然而,如果IntoIterator并不总是合适的话,那就是选择,因为它意味着所有权的转移.如果你只是想借用HashMap用于只读目的,你可能会更好地使用HashMap的标准迭代器特性,Iterator< Item =(&’a String,&’vec< String>)&gt ;.

fn foo_iter<'a, I>(input: I)
where I: Iterator<Item=(&'a String, &'a Vec<String>)>

与第一个版本不同,您可以通过请求新的迭代器多次使用它.

let mut h = HashMap::new();
h.insert("The Beatles".to_string(), 
    vec!["Come Together".to_string(),
         "Twist And Shout".to_string()]);
h.insert("The Rolling Stones".to_string(), 
    vec!["Paint It Black".to_string(), 
         "Satisfaction".to_string()]);
foo_iter(h.iter());
foo_iter(h.iter());
foo(h);
//foo(h); <-- error: use of moved value: `h`

Full gist

编辑

正如评论中所述,这里是嵌套的IntoIterators的foo版本,而不是更简单的Vec:

fn foo<I, IVecString>(input: I)
where 
I: IntoIterator<
    Item=(String, IVecString), 
    IntoIter=std::collections::hash_map::IntoIter<String, IVecString>>,
IVecString: IntoIterator<
    Item=String,
    IntoIter=std::vec::IntoIter<String>>
点赞