如何从Map生成Iter?迭代器装饰代码编译失败求助
问题分析与解决方案
核心问题
你的代码无法编译的原因是:
Iter<String>是仅用于遍历&[String]切片的专属迭代器类型,但filter+map组合后生成的是匿名组合迭代器(类型为Map<Filter<Iter<Person>, ...>, ...>),和Iter<String>完全不是同一类型,无法强制转换。- 另外,若
map返回String(假设name()转移所有权),迭代器元素是String,而Iter<String>的元素是&String,类型不匹配;即使name()返回&String,迭代器类型依然不兼容。
符合要求的解决方案
你不想收集到Vec且要保持兼容性,最佳方案是返回impl Iterator类型——这是Rust中返回组合迭代器的标准方式,可被任何接受迭代器的代码使用,完全满足兼容性要求,同时避免额外内存分配。
示例代码(name()返回引用)
use std::slice::Iter; struct Person { name: String, is_friend: bool, } impl Person { fn is_my_friend(&self) -> bool { self.is_friend } fn name(&self) -> &String { &self.name } } // 返回impl Iterator,明确迭代器元素类型为&String fn only_friend_names(i: Iter<Person>) -> impl Iterator<Item = &String> { i.filter(|p| p.is_my_friend()).map(|p| p.name()) }
示例代码(name()返回所有权)
如果需要转移String所有权,只需调整Item类型:
fn only_friend_names(i: Iter<Person>) -> impl Iterator<Item = String> { i.filter(|p| p.is_my_friend()).map(|p| p.name().clone()) }
关于返回Iter<String>的可能性
无法实现:Iter<String>只能从&[String]切片生成,而你的逻辑是从&[Person]转换字符串,没有现成的&[String]切片存在(除非收集到Vec<String>再取迭代器,但你明确拒绝这种方式)。因此impl Iterator是唯一符合你性能和兼容性要求的选择。
内容的提问来源于stack exchange,提问作者yegor256
相关产品推荐
相关产品推荐

