Rust中如何优雅从结构体向量筛选并提取目标属性(无额外分配)
Rust 优雅提取匹配结构体的属性值
问题描述
我正尝试通过结构体属性筛选结构体向量,然后返回另一个属性,但不确定如何优雅提取该值。我的函数会接收预算名称,想要通过搜索Budget列表返回对应预算的id。请问有没有无需分配新结构体的单遍遍历的更简洁实现方式?
原代码
// Budget structs #[derive(Serialize, Deserialize, Debug)] pub struct Budgets { pub budgets: Vec<Budget> } #[derive(Serialize, Deserialize, Debug)] pub struct Budget { pub id: String, name: String, last_modified_on: String, first_month: String, last_month: String, date_format: DateFormat, currency_format: Option<CurrencyFormat>, accounts: Option<Accounts>, } impl Adapter { fn get_budget_id(&self, budget_name: &str) -> anyhow::Result<String> { let budget_data = self.get_budgets()?; let budget = budget_data.data.budgets.into_iter() .filter(|b| b.name == budget_name); //.collect::<Budgets>() <-- FromIterator not implemented //.remove(0); let b = Budgets { budgets: Vec::from_iter(budget) }; if b.budgets.is_empty() { Err(anyhow::anyhow!("Error, no budget with {} name found", budget_name)) } else { Ok(b.budgets[0].id.clone()) } } }
优化实现
可以用Iterator::find方法替代filter,它会在找到第一个匹配项后立即停止遍历,无需收集整个向量,完全符合单遍遍历且无额外结构体分配的需求:
impl Adapter { fn get_budget_id(&self, budget_name: &str) -> anyhow::Result<String> { let budget_data = self.get_budgets()?; budget_data.data.budgets.into_iter() .find(|b| b.name == budget_name) .ok_or_else(|| anyhow::anyhow!("Error, no budget with {} name found", budget_name)) .map(|b| b.id.clone()) } }
优化点说明
find替代filter:find只查找第一个匹配的元素,找到后就终止遍历,比filter遍历全部元素更高效,且不需要后续收集操作- 直接处理
Option:find返回Option<Budget>,用ok_or_else把None转换成错误类型,map直接提取id并克隆,整个流程链式调用,代码更简洁 - 无额外分配:全程不需要创建新的
Budgets结构体或临时向量,避免不必要的内存分配
内容的提问来源于stack exchange,提问作者seve
相关产品推荐
相关产品推荐

