如何在Rust的单次迭代中从.map()输出多个值,或对同一个into_iter两次调用map?
嘿,先提个小问题——你当前的代码其实会编译失败哦!因为into_iter()会拿走v.result.transactions的所有权,第一次调用后,这个字段就不能再被第二次into_iter()使用了。不过没关系,我们正好可以解决这个问题的同时,实现一次遍历合并两个数组的需求~
方案1:用flat_map(函数式风格首选)
flat_map是Rust迭代器里的神器,它可以把每个元素转换成一个子迭代器,然后自动把所有子迭代器的元素拼接成一个大的迭代器。正好适合我们每个交易需要输出两个字符串的场景:
// 先修正类型写法,Vec<"String">是错误的,应该是Vec<String> let combined: Vec<String> = v.result.transactions.into_iter() .flat_map(|tx| [tx.from, tx.to].into_iter()) // 每个交易生成含两个元素的迭代器 .collect();
解释一下:
- 闭包
|tx| [tx.from, tx.to].into_iter()把每个EthTransactionObj转换成包含from和to的数组迭代器 flat_map会把这些小迭代器"铺平",最终得到一个连续的String迭代器- 最后用
collect()把迭代器转换成Vec<String>
方案2:用fold(更偏向命令式但易懂)
如果你觉得flat_map有点抽象,fold(也就是"折叠"操作)也能完成任务。它会维护一个累加器,我们可以在遍历每个交易时,把from和to逐个加到累加器里:
let combined: Vec<String> = v.result.transactions.into_iter() .fold(Vec::new(), |mut acc, tx| { acc.push(tx.from); acc.push(tx.to); acc // 返回更新后的累加器给下一次迭代 });
关于你提到的两个想法
能输出两个值的闭包? 闭包可以返回元组(比如
|tx| (tx.from, tx.to)),但这样你得到的是Vec<(String, String)>,还需要额外一步把元组拆成单个元素。而flat_map其实已经帮我们完成了"拆元组/生成多元素"的工作,是更简洁的选择。一次迭代中两次使用map? 不行哦,
map的作用是把每个元素转换成一个新值,一次map只能得到一个元素对应一个输出。如果要一个元素对应多个输出,就得用flat_map这种能生成多元素迭代器的方法,或者像fold那样手动处理累加。
另外还要纠正你代码里的小语法错误:
- 结构体定义里的
from: "String"应该写成from: String(引号要去掉,"String"是字符串字面量类型,不是我们需要的String类型) Vec<"String">也要改成Vec<String>
内容的提问来源于stack exchange,提问作者DedicatedDreamer
相关产品推荐
相关产品推荐

