You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 13:54:24