![](/img/trans.png)
[英]Iterating over std::map<X,std::vector<Y> > and sorting the vectors
[英]Iterating generically over either a map or a vector of 2-tuples
由於原因 ,我想定義一個泛型函數,它可以迭代表示為映射的鍵值對,或者作為2元組的向量(或滿足IntoIterator<Item=(K, V)>
任何其他IntoIterator<Item=(K, V)>
,其中K
和V
是粘性的)。 具體來說,我想要這個工作:
use std::collections::HashMap;
fn main() {
let vc = vec![
("a", "foo"),
("b", "bar"),
("c", "baz")
];
operate(&vc);
let mut map = HashMap::new();
map.insert("d", "blurf");
map.insert("e", "quux");
map.insert("f", "xyzzy");
operate(&map);
}
我有一個適用於HashMap的operate
定義,但不適用於矢量:
fn operate<I, K, V>(x: I)
where I: IntoIterator<Item=(K, V)>,
K: AsRef<str>, V: AsRef<str>
{
for (ref k, ref v) in x {
println!("{}: {}", k.as_ref(), v.as_ref());
}
}
我得到的錯誤信息是
error[E0271]: type mismatch resolving `<&std::vec::Vec<(&str, &str)> as std::iter::IntoIterator>::Item == (_, _)`
--> test.rs:18:5
|
18 | operate(&vc);
| ^^^^^^^ expected reference, found tuple
|
= note: expected type `&(&str, &str)`
= note: found type `(_, _)`
= note: required by `operate`
而且我根本不明白。 首先,它似乎是倒退,而另一方面,為什么我只得到Vec
而不是HashMap
的錯誤?
IntoIterator
提供的功能消耗自我。
fn into_iter(self) -> Self::IntoIter
為了允許在不使用集合的情況下使用IntoIterator
, Vec
和HashMap
分別實現了對於&'a Vec<T>
和&'a HashMap<K,V,S>
的IntoIterator
。 但是,它們並不完全相同。
對於哈希映射,每個Item
都是(&K, &V)
,它不會產生問題,因為代碼有效地將項目視為2個大小的鍵元組和強制轉換為&str
值。 並且&&str
確實強制到&str
。 對於向量,每個Item
都是&T
(因此在這種情況下為&(K, V)
),但由於函數期望(K, V)
作為迭代項,因此它目前無法處理&(K, V)
。
實際上,如果移動向量,該函數將起作用,從而產生一個其中Item = (K, V)
的IntoIterator
:
let vc = vec![
("a", "foo"),
("b", "bar"),
("c", "baz")
];
operate(vc);
但是,如果我們希望它能夠在不消耗任何產品的情況下為兩個系列工作呢? 好吧,我剛剛設計了兩個解決方案。
這個涉及將元組隱藏在一個新的特征背后:
/// for stuff that can be turned into a pair of references
trait AsRefPair<K, V> {
fn as_ref_pair(&self) -> (&K, &V);
}
為&(K,V)
和(&K,&V)
實現它:
impl<'a, K, V> AsRefPair<K, V> for (&'a K, &'a V) {
fn as_ref_pair(&self) -> (&K, &V) {
(self.0, self.1)
}
}
impl<'a, K, V> AsRefPair<K, V> for &'a (K, V) {
fn as_ref_pair(&self) -> (&K, &V) {
(&self.0, &self.1)
}
}
現在這個功能有效:
fn operate<I, T, K, V>(x: I)
where I: IntoIterator<Item=T>,
T: AsRefPair<K, V>,
K: AsRef<str>, V: AsRef<str>
{
for p in x {
let (ref k, ref v) = p.as_ref_pair();
println!("{}: {}", k.as_ref(), v.as_ref());
}
}
游樂場 。 起初聽起來有點瘋狂,但是......!
在這一個中,只需停止使用元組...並開始使用鍵值!
trait KeyValue<K, V> {
fn key_value(&self) -> (&K, &V) {
(self.key(), self.value())
}
fn key(&self) -> &K;
fn value(&self) -> &V;
}
impl<K, V> KeyValue<K, V> for (K, V) {
fn key(&self) -> &K {
&self.0
}
fn value(&self) -> &V {
&self.1
}
}
impl<'a, K, V> KeyValue<K, V> for &'a (K, V) {
fn key(&self) -> &K {
&self.0
}
fn value(&self) -> &V {
&self.1
}
}
fn operate<I, T, K, V>(x: I)
where I: IntoIterator<Item=T>,
T: KeyValue<K, V>,
K: AsRef<str>, V: AsRef<str>
{
for p in x {
let (ref k, ref v) = p.key_value();
println!("{}: {}", k.as_ref(), v.as_ref());
}
}
游樂場 。 我發現這個更慣用。
如果傳遞函數operate()
迭代器而不是向量的引用,則可以使用Iterator
適配器將Iterator::Item
轉換為您需要的:
operate(vc.iter().map(|&(ref a, ref b)| (a, b)));
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.