如何在同一个函数中结合使用IntoKeys和IntoIter?
如何在同一个函数中结合使用IntoKeys和IntoIter?
嘿,看了你的代码,这编译失败的问题其实挺典型的——咱来拆解下:
首先,你在match里返回的两个迭代器类型不一样:map.into_keys()给的是IndexMap专属的IntoKeys迭代器,而vec.into_iter()是Vec的IntoIter迭代器。Rust的match可是个死心眼,要求所有分支必须返回完全相同的类型,所以编译器直接给你报错了。另外还有个小疏漏:你最后没加collect(),哪怕前面都对了,也没法把迭代器转成Vec<String>返回哦。
给你两种解决办法,优先推荐第一种,因为性能更好:
方法一:用either::Either统一迭代器类型
你已经导入了either crate,刚好可以用它的Either来包裹两个不同的迭代器——只要它们的Item类型相同(都是String),Either就会自动实现Iterator trait,完美解决类型不统一的问题:
use indexmap::IndexMap; use either::Either; type Atom = Either<IndexMap<String, u64>, Vec<String>>; fn flatten(atoms: Vec<Option<Atom>>) -> Vec<String> { atoms.into_iter() // 用flatten直接处理Option,比filter+unwrap更简洁 .flatten() .flat_map(|atom| match atom { Either::Left(map) => Either::Left(map.into_keys()), Either::Right(vec) => Either::Right(vec.into_iter()), }) // 别忘了最后把迭代器收集成Vec .collect() }
方法二:用装箱Trait对象(动态分发)
如果不想用either,也可以把迭代器装箱成Box<dyn Iterator<Item = String>>,这样两个分支就都是同一个 trait 对象类型了。不过这种方法会有一点点运行时开销,因为是动态分发:
use indexmap::IndexMap; use either::Either; type Atom = Either<IndexMap<String, u64>, Vec<String>>; fn flatten(atoms: Vec<Option<Atom>>) -> Vec<String> { atoms.into_iter() .filter(Option::is_some) .map(|atom| match atom.unwrap() { Either::Left(map) => Box::new(map.into_keys()) as Box<dyn Iterator<Item = String>>, Either::Right(vec) => Box::new(vec.into_iter()) as Box<dyn Iterator<Item = String>>, }) .flatten() .collect() }
备注:内容来源于stack exchange,提问作者gust
相关产品推荐
相关产品推荐

