使用FlatMap迭代器时为何报错FromIterator<&{integer}>未实现于Vec<i32>?
为什么FlatMap迭代器会出现这个类型不匹配错误?
这问题我之前写Rust的时候也踩过坑,其实核心就是迭代器输出的元素类型和你要收集的目标类型不匹配,咱们一步步拆解来看:
先看你的代码里迭代器的元素类型
fn main() { let arr_of_arr = [[1, 2], [3, 4]]; let res = arr_of_arr .iter() // 这里返回的迭代器元素是 &[i32; 2](数组的引用) .flat_map(|arr| arr.iter()) // arr是&[i32;2],arr.iter()返回的迭代器元素是 &i32(整数的引用) .collect::<Vec<i32>>(); // 你要收集成Vec<i32>,但迭代器给的是&i32,类型不匹配! }
编译器报错的意思很直白:它没办法用&i32类型的元素来构建Vec<i32>——因为Vec<i32>的FromIterator trait只实现了从i32迭代器收集,没实现从&i32收集。
解决方法有这几种,按需选就行:
1. 把引用转换成值(最常用)
因为i32是实现了Copy trait的基础类型,直接用copied()或者cloned()把&i32转成i32就行:
fn main() { let arr_of_arr = [[1, 2], [3, 4]]; let res = arr_of_arr .iter() .flat_map(|arr| arr.iter().copied()) // 用copied()复制引用里的值 .collect::<Vec<i32>>(); }
copied():只适用于实现Copy的类型,直接复制值,性能更好cloned():更通用,只要类型实现Clone就可以,比如String这种非Copy类型也能用
2. 直接迭代所有权(不需要保留原数组时用)
如果你之后不需要再用arr_of_arr了,可以用into_iter()代替iter(),直接获取数组的所有权,这样迭代出来的就是值而不是引用:
fn main() { let arr_of_arr = [[1, 2], [3, 4]]; let res = arr_of_arr .into_iter() // 获取数组所有权,元素是[i32;2] .flat_map(|arr| arr.into_iter()) // arr是[i32;2],into_iter()返回i32的迭代器 .collect::<Vec<i32>>(); }
3. 用flatten()简化写法(和flat_map效果一致)
Rust里还提供了flatten()方法,专门用来扁平化嵌套迭代器,和你的flat_map(|arr| arr.iter())效果一样,不过同样要注意转值:
fn main() { let arr_of_arr = [[1, 2], [3, 4]]; let res = arr_of_arr .iter() .flatten() // 等价于flat_map(|arr| arr.iter()),元素还是&i32 .copied() .collect::<Vec<i32>>(); }
总结一下
写Rust迭代器的时候一定要注意每一步迭代器输出的元素类型,尤其是iter()和into_iter()的区别:前者返回引用迭代器,后者返回所有权迭代器。只要让迭代器的元素类型和目标集合的元素类型匹配,这个错误就解决啦~
内容的提问来源于stack exchange,提问作者attdona
相关产品推荐
相关产品推荐

