如何在Rust中基于字符串contains方法过滤自定义结构体向量
Rust中使用filter结合contains过滤自定义结构体向量
我已经看过相关问题但未找到解决方案,核心区别是我需要在过滤逻辑中使用字符串的contains()方法,以下是具体场景和问题:
定义的结构体
#[derive(Clone)] pub struct Spell { pub title: String, pub code: String, pub category: String, pub sub_category: String, pub tool: String, pub file_name: String, } #[derive(Debug)] pub struct SearchParameters { pub category: String, pub sub_category: String, pub tool: String, pub search_str: String, }
原处理函数的问题
我原本的函数通过多次filter处理向量,但最后一个filter块中尝试使用contains()时编译报错,只能通过后续循环二次处理结果,这种方式不够优雅:
pub fn search_spell(&self, search_parameters: SearchParameters) -> Vec<Spell> { let tmp_results: Vec<Spell> = self ._spell_list .clone() .into_iter() .filter(|spell| { if search_parameters.category.is_empty() { true } else { *spell.category == search_parameters.category } }) .filter(|spell| { if search_parameters.sub_category.is_empty() { true } else { *spell.sub_category == search_parameters.sub_category } }) .filter(|spell| { if search_parameters.tool.is_empty() { true } else { *spell.tool == search_parameters.tool } }) .filter(|spell| { if search_parameters.search_str.is_empty() { true } else { //*spell.title.contains(search_parameters.search_str) true } }) .collect(); // TODO: replace this part by including in the filer above let mut results: Vec<Spell> = Vec::new(); for spell in tmp_results { if search_parameters.search_str.is_empty() { results.push(spell); } else { if spell .title .to_lowercase() .contains(&search_parameters.search_str.to_lowercase()) { results.push(spell); } } } results }
优化后的解决方案
可以将所有过滤逻辑合并到一个filter中,同时提前处理搜索字符串的小写转换以提升性能,解决编译问题:
pub fn search_spell(&self, search_parameters: SearchParameters) -> Vec<Spell> { // 提前转换搜索字符串为小写,避免每个元素迭代时重复计算 let search_str_lower = search_parameters.search_str.to_lowercase(); // 解构参数变量,避免闭包捕获时的所有权冲突 let category = search_parameters.category; let sub_category = search_parameters.sub_category; let tool = search_parameters.tool; self._spell_list .clone() .into_iter() .filter(|spell| { // 依次判断各过滤条件 let category_match = category.is_empty() || spell.category == category; let sub_cat_match = sub_category.is_empty() || spell.sub_category == sub_category; let tool_match = tool.is_empty() || spell.tool == tool; let search_match = search_str_lower.is_empty() || spell.title.to_lowercase().contains(&search_str_lower); // 所有条件满足才保留 category_match && sub_cat_match && tool_match && search_match }) .collect() }
关键说明
- 合并filter:将多个
filter合并为一个,减少迭代次数,提升效率 - 提前处理小写转换:只对搜索字符串做一次
to_lowercase(),避免每个元素迭代时重复转换,节省性能 - 解决类型与所有权问题:
contains()方法需要接收&str类型参数,因此传入&search_str_lower(search_str_lower是String,取引用后符合要求)- 提前解构
search_parameters的字段,避免闭包捕获整个结构体时的所有权冲突
内容的提问来源于stack exchange,提问作者0x4ndy
相关产品推荐
相关产品推荐

