つまずいた場所
let vec: Vec<String> = vec![
"hoge".to_string(),
"fuga".to_string(),
"piyopiyo".to_string(),
];
// 要素がコピーされた Vec が出来る
let filtered_vec: Vec<String> =
vec.iter().filter(|s| s.len() <= 5).cloned().collect();
let mut map: HashMap<i32, String> = HashMap::new();
map.insert(0, "hoge".to_string());
map.insert(1, "fuga".to_string());
map.insert(2, "piyopiyo".to_string());
// error[E0271]: type mismatch resolving ...
let filtered_map: HashMap<i32, String> =
map.iter().filter(|(_k, v)| v.len() <= 5).cloned().collect();
ナンデ?
理由
まず cloned は Iterator<Item=&T> を Iterator<Item=T> に変換するもの。
つまり参照を受けて値に変換する。
しかし HashMap::iter は Iterator<Item=(&Key, &Value)> を返す。
この時、 (&Key, &Value) は参照を格納した値であって、それ自体は参照ではない。
解決法
前述の理由により、無理やり
.map(|pair| pair.clone())
としてもシャローコピーされるだけで上手くいかない。
.map(|(k, v)| (k.clone(), v.clone()))
とする必要がある。
今回は i32 が Copy なので、
.map(|(&k, v)| (k, v.clone()))
でも可。
短くかける方法があれば教えてください。